home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / go / prog / igc060.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  1993-06-20  |  80.3 KB  |  3,824 lines

  1. #! /bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #! /bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create:
  6. #    README
  7. #    socket.c
  8. #    igc.c
  9. #    parse.c
  10. #    ascii.c
  11. #    board.c
  12. #    numbers.h
  13. #    igc.h
  14. #    Makefile
  15. #    igc.6
  16. # This archive created: Sat Dec  5 23:18:01 1992
  17. export PATH; PATH=/bin:/usr/bin:$PATH
  18. if test -f 'README'
  19. then
  20.     echo shar: "will not over-write existing file 'README'"
  21. else
  22. cat << \SHAR_EOF > 'README'
  23.         IGS - Ascii Client by Adrian Mariano
  24.                 adrian@u.washington.edu
  25.                            adrian on igs
  26.  
  27.  
  28. This is an ascii client program for the Internet Go Server.
  29.  
  30. Its purpose is to provide a useable interface to the server with
  31. ASCII character drawn Go boards.
  32.  
  33. This program requires UNIX with sockets capability. 
  34.  
  35. Read the Makefile for instructions on compiling.
  36.  
  37. SHAR_EOF
  38. fi
  39. if test -f 'socket.c'
  40. then
  41.     echo shar: "will not over-write existing file 'socket.c'"
  42. else
  43. cat << \SHAR_EOF > 'socket.c'
  44. #include <sys/types.h>
  45. #include <sys/time.h>
  46. #include <sys/socket.h>
  47. #include <netdb.h>
  48.  
  49. #ifndef WINS            /* Usually want this... */
  50. #include <netinet/in.h>
  51. #else                /* ... but need these for WINS. */
  52. #include <sys/in.h>
  53. #include <sys/inet.h>
  54. #endif
  55.  
  56. #include <fcntl.h>
  57. #include <sys/errno.h>
  58. #include <stdio.h>
  59. #ifndef FD_ZERO
  60. #include <sys/select.h>
  61. #endif
  62. #include "igc.h"
  63.  
  64. /* For some odd systems, which don't put this in errno.h. */
  65.  
  66. extern int errno;
  67.  
  68. char servename[80];
  69. int serveport;
  70. int sock;
  71. char inbuf[1000];
  72. int inptr = 0;
  73.  
  74.  
  75. sethost(s)
  76. char *s;
  77. {
  78.    strcpy(servename, s);
  79. }
  80.  
  81.  
  82. setport(s)
  83. int s;
  84. {
  85.    serveport = s;
  86.  
  87. }
  88.  
  89. void close_connection()
  90. {
  91.    close(sock);
  92. }
  93.  
  94.  
  95. #ifdef DEBUG
  96. FILE *blah;
  97. #endif
  98.  
  99. int open_connection()
  100. {
  101.    struct sockaddr_in server;
  102.    struct hostent *hp;
  103.    int ipn;
  104.  
  105.    printf("Opening connection to %s %d\n", servename, serveport);
  106. #ifdef DEBUG
  107.    {
  108.       int d;
  109.       char n[444];
  110.       d = 0;
  111.       do {
  112.      sprintf(n, "dump%d.igc", d);
  113.      blah = fopen(n, "r");
  114.      if (!blah) {
  115.         blah = fopen(n, "w");
  116.         if (blah)
  117.            printf("Creating dump file %s\n", n);
  118.         break;
  119.      }
  120.      close(blah);
  121.      d++;
  122.      if (d > 9) {
  123.         printf("Too many dump files.  Delete dump files (dump?.igc)? ");
  124.         fgets(n, 443, stdin);
  125.         if (n[0] != 'Y' && n[0] != 'y')
  126.            exit(1);
  127.         for (d = 0; d < 10; d++) {
  128.            sprintf(n, "dump%d.igc", d);
  129.            unlink(n);
  130.         }
  131.         blah = fopen("dump0.igc", "w");
  132.         if (!blah) {
  133.            printf("File open error.  Cannot create dump file\n");
  134.            exit(1);
  135.         }
  136.         break;
  137.      }
  138.       } while (1);
  139.       if (!blah) {
  140.      printf("File open error.  Cannot create dump file.\n");
  141.      exit(1);
  142.       }
  143.    }
  144. #endif
  145.    if (sscanf(servename, "%d.%d.%d.%d", &ipn, &ipn, &ipn, &ipn) == 4)
  146.       server.sin_addr.s_addr = inet_addr(servename);
  147.    else {
  148.       hp = gethostbyname(servename);
  149.       if (hp == 0) {
  150.      puts("Unknown host");
  151.      return -1;
  152.       }
  153.       bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  154.    }
  155.    server.sin_family = AF_INET;
  156.    server.sin_port = htons(serveport);
  157.    sock = socket(AF_INET, SOCK_STREAM, 0);
  158.    if (sock < 0) {
  159.       perror("socket");
  160.       return -1;
  161.    }
  162.    if (connect(sock, (struct sockaddr *) & server,
  163.            sizeof(struct sockaddr_in)) < 0) {
  164.       perror("connect");
  165.       return -1;
  166.    }
  167.    return 0;
  168. }
  169.  
  170.  
  171.  
  172. sendstr(buf)
  173. char *buf;
  174. {
  175.  
  176. #ifdef DEBUG
  177.    if (strlen(buf) && blah)
  178.       fprintf(blah, ">%s<\n", buf);
  179. #endif
  180.    write(sock, buf, strlen(buf));
  181. }
  182.  
  183.  
  184. int eatchar = 0;
  185.  
  186. int handlechar(retbuf, in)
  187. char *retbuf;
  188. char in;
  189. {
  190.    if (in == '\r')
  191.       return 0;
  192. #ifdef DEBUG
  193.    fputc(in, blah);
  194. #endif
  195.    if (eatchar) {
  196.       eatchar--;
  197.       return 0;
  198.    }
  199.    if (in == '\377') {
  200.       eatchar = 2;
  201.       return 0;
  202.    }
  203.    if (in == '\n') {
  204.       inbuf[inptr] = 0;
  205.       strcpy(retbuf, inbuf);
  206.       inptr = 0;
  207.       return 1;
  208.    } else {
  209.       inbuf[inptr++] = in;
  210.       if (doneline(inbuf, inptr)) {
  211.      inbuf[inptr] = 0;
  212.      strcpy(retbuf, inbuf);
  213.      inptr = 0;
  214.      return 1;
  215.       }
  216.    }
  217.    return 0;
  218. }
  219.  
  220.  
  221.  
  222. int bufdata = 0, bufptr = 0;
  223. char thebuf[1000];
  224.  
  225. int pollserver(retbuf, checkstdin)
  226. char *retbuf;
  227. int checkstdin;
  228. {
  229.    int sel;
  230.    fd_set readers;
  231.  
  232.    FD_ZERO(&readers);
  233.    while (1) {
  234.       while (bufdata) {
  235.      bufdata--;
  236.      if (handlechar(retbuf, thebuf[bufptr++]))
  237.         return 1;
  238.       }
  239.       bufptr = 0;
  240.       if (checkstdin)
  241.      FD_SET(0, &readers);    /* Check stdin */
  242.       FD_SET(sock, &readers);
  243.       sel = select(sock + 1, &readers, NULL, NULL, (struct timeval *) 0);
  244.       if (sel == -1) {
  245.      if (errno != EINTR) {    /* ^Z will do this */
  246.         perror("select");
  247.         return -1;
  248.      }
  249.      continue;
  250.       }
  251.       if (FD_ISSET(sock, &readers)) {
  252.      bufdata = read(sock, thebuf, 1000);
  253.      if (!bufdata)
  254.         return -1;
  255.      if (bufdata < 0) {
  256.         perror("read");
  257.         return -2;
  258.      }
  259.       } else if (FD_ISSET(0, &readers))
  260.      return KEY;
  261.    }
  262. }
  263. SHAR_EOF
  264. fi
  265. if test -f 'igc.c'
  266. then
  267.     echo shar: "will not over-write existing file 'igc.c'"
  268. else
  269. cat << \SHAR_EOF > 'igc.c'
  270. #include "igc.h"
  271. #include <stdio.h>
  272. #include <string.h>
  273. #include <signal.h>
  274. #include <pwd.h>
  275. #include "numbers.h"
  276.  
  277.  
  278. #define RCNAME "/.igcrc"
  279.  
  280. char login[20] = "";
  281. char password[20] = "";
  282.  
  283. message mesg;            /* structure for getting parsed info from
  284.                  * server */
  285.  
  286. char prefix[21];        /* Text prefix for each outgoing line */
  287. int xcur = -1, ycur = -1;    /* Cursor locations on board */
  288. int boardon = 0;        /* Is the board being displayed? */
  289. int boardmode = 0;        /* Are we on the board? */
  290. int beepcount = 1;        /* Number of beeps to send */
  291. int saybeep = 0;        /* Beep on say strings? */
  292. int tellbeep = 0;        /* Beep on tell strings? */
  293.  
  294. int ingame = -1;        /* Game which is displayed, -1 for none */
  295. int observing = 0;        /* Are we observing a game? */
  296. int justpeeked = 0;        /* Fixup flag for game number after peek */
  297. int needrestore = 0;        /* Need to restore board? (After status) */
  298. int bschange = 0;        /* boardsize changed?  Used with needrestore */
  299. extern int boardsize;
  300.  
  301. char local[1000], *loc;        /* Buffer for characters typed by local user */
  302.  
  303. struct {
  304.    char white[21], wrank[10], black[21], brank[10];
  305.    int hcap;
  306.    float komi;
  307.    int bbyo, wbyo, wtime, btime;
  308. }  curgame;            /* Information about current game */
  309.  
  310.  
  311. int (*whosort) ();
  312.  
  313. struct {
  314.    char name[50];
  315.    char site[100];
  316.    int port;
  317. }  sitetable[10] =
  318. {
  319.    {
  320.       "icsi", "icsib18.icsi.Berkeley.EDU", 6969
  321.    },
  322.    {
  323.       "cnam", "cnam.cnam.fr", 6969
  324.    },
  325.    {
  326.       "", "", 6969
  327.    },
  328.    {
  329.       "", "", 6969
  330.    },
  331.    {
  332.       "", "", 6969
  333.    },
  334.    {
  335.       "", "", 6969
  336.    },
  337.    {
  338.       "", "", 6969
  339.    },
  340.    {
  341.       "", "", 6969
  342.    },
  343.    {
  344.       "", "", 6969
  345.    },
  346.    {
  347.       "", "", 6969
  348.    }
  349.  
  350. };
  351.  
  352.  
  353. char *getpassword(repeat)
  354. int repeat;
  355. {
  356.    if (repeat || !strlen(password)) {
  357.       printf("Password: ");
  358.       for (;;) {
  359.      gets(password);
  360.      if (strstr(password, "helpigc"))
  361.         printf("You are entering your password for the Internet Go Server.  You will be\nprompted twice for your password if you are creating a new account.  Enter\nthe same password twice in this case.\nPassword: ");
  362.      else if (!strlen(password))
  363.         printf("Empty password not allowed.\nPassword: ");
  364.      else
  365.         break;
  366.       }
  367.    }
  368.    return password;
  369. }
  370.  
  371.  
  372. char *getloginname(repeat)
  373. int repeat;
  374. {
  375.    if (repeat == 1)
  376.       printf("Login failed.\n");
  377.    if (repeat || !strlen(login)) {
  378.       printf("Login: ");
  379.       for (;;) {
  380.      gets(login);
  381.      if (strstr(login, "helpigc"))
  382.         printf("You are logging into the Internet Go server.  Type a login name now.\nLogin: ");
  383.      else if (!strlen(login))
  384.         printf("Blank names not allowed.\nLogin: ");
  385.      else
  386.         break;
  387.       }
  388.    } else
  389.       printf("Logging on as %s\n", login);
  390.    return login;
  391. }
  392.  
  393.  
  394.  
  395. putstr(s)
  396. char *s;
  397. {
  398.    if (boardon) {
  399.       addstring(s);
  400.       addchar('\n');
  401.    } else
  402.       puts(s);
  403. }
  404.  
  405.  
  406. dobeep()
  407. {
  408.    char ch;
  409.    for (ch = beepcount; ch--;)
  410.       putchar(7);
  411. }
  412.  
  413.  
  414. readrc()
  415. {
  416.  
  417.    int id;
  418.    struct passwd *pw;
  419.    char *dir, rcfilename[1000];
  420.    FILE *rcfile;
  421.    char *var, *val, line[100];
  422.  
  423.    id = geteuid();
  424.    pw = getpwuid(id);
  425.    dir = pw->pw_dir;
  426.    strcpy(rcfilename, dir);
  427.    strcat(rcfilename, RCNAME);
  428.    if (rcfile = fopen(rcfilename, "rt")) {
  429.       while (fgets(line, 99, rcfile)) {
  430.      var = strtok(line, " \t=\n");
  431.      if (!var)
  432.         continue;
  433.      val = strtok(NULL, " \t=\n");
  434.      if (!strcmp(var, "password"))
  435.         strcpy(password, val);
  436.      if (!strcmp(var, "login"))
  437.         strcpy(login, val);
  438.      if (!strncmp(var, "site", 4) && var[4] >= '0' && var[4] <= '9') {
  439.         strcpy(sitetable[var[4] - '0'].name, val);
  440.         val = strtok(NULL, "\t=\n ");
  441.         strcpy(sitetable[var[4] - '0'].site, val);
  442.  
  443.         if (val = strtok(NULL, "\t= \n"))
  444.            sitetable[var[4] - '0'].port = atoi(val);
  445.         else
  446.            sitetable[var[4] - '0'].port = 6969;
  447.      }
  448.      if (!strcmp(var, "saybeep"))
  449.         saybeep = 1;
  450.      if (!strcmp(var, "nosaybeep"))
  451.         saybeep = 0;
  452.      if (!strcmp(var, "tellbeep"))
  453.         tellbeep = 1;
  454.      if (!strcmp(var, "notellbeep"))
  455.         tellbeep = 0;
  456.      if (!strcmp(var, "beeps"))
  457.         beepcount = atoi(val);
  458.      if (!strcmp(var, "inverse"))
  459.         setinverse(1);
  460.      if (!strcmp(var, "noinverse"))
  461.         setinverse(0);
  462.      if (!strcmp(var, "noinvedge"))
  463.         setinverseborder(0);
  464.      if (!strcmp(var, "invedge"))
  465.         setinverseborder(1);
  466.      if (!strcmp(var, "edgemarks"))
  467.         setedgemark(1);
  468.      if (!strcmp(var, "noedgemarks"))
  469.         setedgemark(0);
  470.      if (!strcmp(var, "piecemarks"))
  471.         setpiecemark(1);
  472.      if (!strcmp(var, "nopiecemarks"))
  473.         setpiecemark(0);
  474.      if (!strcmp(var, "sort"))
  475.         choosesort(val);
  476.      if (!strcmp(var, "border")) {
  477.         if (!val)
  478.            setborder(' ');
  479.         else
  480.            setborder(*val);
  481.      }
  482.      if (!strcmp(var, "chars") && val)
  483.         setchars(val);
  484.       }
  485.    }
  486. }
  487.  
  488.  
  489.  
  490. void myexit(ex)
  491. int ex;
  492. {
  493.    if (boardon)
  494.       endAscii();
  495.    exit(ex);
  496. }
  497.  
  498. void handletstp()
  499. {
  500.    signal(SIGTSTP, handletstp);
  501.    if (boardon)
  502.       suspend();
  503.    kill(getpid(), SIGSTOP);
  504.    if (boardon) {
  505.       unsuspend();
  506.       if (boardmode)
  507.      boardrefresh();
  508.       else
  509.      serverrefresh();
  510.    }
  511. }
  512.  
  513.  
  514. void handleterm()
  515. {
  516.    close_connection();
  517.    myexit(0);
  518. }
  519.  
  520.  
  521. int startgame(n)
  522. int n;
  523. {
  524.    char str[100], str2[30];
  525.    int ret, gotmove;
  526.  
  527.    gotmove = 0;
  528.  
  529.    sprintf(str, "games %d\n", n);
  530.    sendstr(str);
  531.    do {
  532.       do {
  533.      ret = getmessage(&mesg, 0);
  534.      if (ret < 0)
  535.         handleterm();
  536.       } while (!ret);
  537.       if (mesg.id == MOVE) {
  538.      if (mesg.movecount)
  539.         putstr("%Premature move.  Restart game.");
  540.      else
  541.         gotmove = 1;
  542.       }
  543.    }
  544.    while (mesg.id != GAMES);
  545.    if (mesg.gamecount != 1 || mesg.gamelist[0].gnum != n)
  546.       return -1;
  547.    if (mesg.gamelist[0].bsize > 19) {
  548.       putstr("%Boardsize too large");
  549.       return -1;
  550.    }
  551.    strcpy(curgame.white, mesg.gamelist[0].white);
  552.    strcpy(curgame.black, mesg.gamelist[0].black);
  553.    strcpy(curgame.brank, mesg.gamelist[0].brank);
  554.    strcpy(curgame.wrank, mesg.gamelist[0].wrank);
  555.    curgame.hcap = mesg.gamelist[0].hcap;
  556.    curgame.komi = mesg.gamelist[0].komi;
  557.    if (observing) {
  558.       addstring("Removing observe\n");
  559.       sprintf(str, "observe %d\n", ingame);
  560.       sendstr(str);
  561.       do {
  562.      do {
  563.         ret = getmessage(&mesg, 0);
  564.         if (ret < 0)
  565.            handleterm();
  566.      } while (!ret);
  567.       } while (mesg.id != PROMPT);
  568.       observing = 0;
  569.    }
  570.    ingame = n;
  571.    initboard(mesg.gamelist[0].bsize);
  572.    displaygamenumber(ingame);
  573.    xcur = ycur = mesg.gamelist[0].bsize / 2;
  574.    sprintf(str, "%s (%s)", curgame.black, curgame.brank);
  575.    sprintf(str2, "%s (%s)", curgame.white, curgame.wrank);
  576.    boardtitle(str, str2);
  577.    if (gotmove)
  578.       highlight(0, 0, 0, 0, mesg.btime, mesg.bbyo, mesg.wtime, mesg.wbyo);
  579.    showkomi(curgame.komi);
  580.    boardon = 1;
  581.    return 0;
  582. }
  583.  
  584.  
  585. getmoves(n)
  586. int n;
  587. {
  588.    char str[20];
  589.  
  590.    sprintf(str, "moves %d\n", n);
  591.    sendstr(str);
  592. }
  593.  
  594.  
  595. unobserve()
  596. {
  597.    char str[20];
  598.    sprintf(str, "observe %d\n", ingame);
  599.    sendstr(str);
  600. }
  601.  
  602.  
  603. int observegame(n)
  604. int n;
  605. {
  606.    int ret;
  607.    char str[20];
  608.    if (n < 0)
  609.       return 1;
  610.    /* if (!observing && ingame != -1) { putstr("%Can't observe while
  611.     * playing."); return 1; } */
  612.    if (startgame(n))
  613.       return 1;
  614.    sprintf(str, "observe %d\n", n);
  615.    sendstr(str);
  616.    observing = 1;
  617.    do {
  618.       do {
  619.      ret = getmessage(&mesg, 0);
  620.      if (ret < 0)
  621.         handleterm();
  622.       } while (!ret);
  623.       if ((mesg.id == INFO) && !strncmp(mesg.text, "Removing", 8))
  624.      putstr("%fatal sync error.  Restart igc.");
  625.    } while (mesg.id != MOVE && mesg.id != UNDO);
  626.    getmoves(n);
  627.    return 0;
  628. }
  629.  
  630.  
  631. int peekgame(n)
  632. int n;
  633. {
  634.    /* if (!observing && ingame != -1) { putstr("Can't peek while playing.");
  635.     * return 1; } */
  636.    if (startgame(n))
  637.       return 1;
  638.    getmoves(n);
  639.    justpeeked = 1;
  640.    setgame(-1);
  641.    return 0;
  642. }
  643.  
  644. setgame(newgame)
  645. int newgame;
  646. {
  647.    if (newgame != ingame) {
  648.       ingame = newgame;
  649.       displaygamenumber(ingame);
  650.    }
  651. }
  652.  
  653. loadgame(name)
  654. char *name;
  655. {
  656.    char str[100];
  657.    int ret;
  658.    sprintf(str, "load %s\n", name);
  659.    sendstr(str);
  660.    do {
  661.       ret = getmessage(&mesg, 0);
  662.       if (ret < 0)
  663.      handleterm();
  664.    } while ((!ret) ||
  665.         (mesg.id != MOVE && mesg.id != ERROR && mesg.id != PROMPT));
  666.    if (mesg.id == ERROR)
  667.       putstr(mesg.text);
  668.    else if (mesg.id == PROMPT)
  669.       putstr("%Load error.");
  670.    else {
  671.       if (!startgame(mesg.gamenum))
  672.      getmoves(mesg.gamenum);
  673.    }
  674. }
  675.  
  676. char *helpmsg = "                   Server Window\n\
  677. unobserve      Stops observing.\n\
  678. peek n         Looks at the board for game n\n\
  679. noboard        Goes back to full screen mode\n\
  680. clear          Clears the window on the right side of the screen\n\
  681. [no]inverse    Switches board to/from inverse \n\
  682. [no]invedge    Turns on/off inversed edges\n\
  683. [no]piecemarks Turns on/off piece marks\n\
  684. [no]edgemarks  Turns on/off edge marks\n\
  685. sort {none|rank|game|name|idle} Chooses sorting order for who command\n\
  686. user <name>    Checks output from last who for <name>\n\
  687. chars <list>   Sets board characters in client\n\
  688. goto n         Goes to a particular move in the current game.\n\
  689. prefix         Sets prefix for all outgoing text you type\n\
  690.                Start commands with '!' to avoid using the prefix\n\
  691. \n\
  692. ESC switches between windows         ^L  refreshes the screen\n\
  693. \n\
  694.                    Board Window\n\
  695. Use number keys (12346789), emacs keys (^P ^N ^F ^B) or rogue keys\n\
  696.    (hjklbnyu) to move the cursor.\n\
  697. Press '0', return, or space to move (send position of cursor)\n\
  698. Press '.' or '>' to move forward through game, ',' or '<' to move backwards.\n\
  699. Press 's' to go to start of game, 'e' to go to end of game.\n\
  700. Press 'c' to clear the current move mark.";
  701.  
  702.  
  703. help()
  704. {
  705.    if (boardon)
  706.       bigmess(25, helpmsg);
  707.    else
  708.       puts(helpmsg);
  709. }
  710.  
  711.  
  712. doargs(argc, argv)
  713. int argc;
  714. char *argv[];
  715. {
  716.    int i;
  717.    for (i = 1; i < argc; i++) {
  718.       if (!strcmp(argv[i], "-s")) {
  719.      int j;
  720.      for (j = i; j < 3; j++)
  721.         argv[j] = argv[j + 1];
  722.      strcpy(login, "");
  723.      strcpy(password, "");
  724.      argc--;
  725.      break;
  726.       }
  727.    }
  728.    if (argc > 3) {
  729.       printf("Too many command line arguments\n\n");
  730.       exit(3);
  731.    }
  732.    if (argc > 1) {
  733.       for (i = 0; i < 10; i++)
  734.      if (!strcmp(argv[1], sitetable[i].name)) {
  735.         sethost(sitetable[i].site);
  736.         setport(sitetable[i].port);
  737.         if (argc > 2) {
  738.            printf("Error: port specified with named host.  Don't use a port number\n");
  739.            printf("when using the shorthand name for a host.\n\n");
  740.            exit(3);
  741.         }
  742.         return;
  743.      }
  744.       sethost(argv[1]);
  745.       if (argc > 2) {
  746.      if (atoi(argv[2]))
  747.         setport(atoi(argv[2]));
  748.      else {
  749.         printf("Illegal port specification\n\n");
  750.         exit(3);
  751.      }
  752.       }
  753.    }
  754. }
  755.  
  756.  
  757. weave()
  758. {
  759.    char *copy[MAXWHO];
  760.    int i, num;
  761.    num = mesg.whocount / 2 + (mesg.whocount & 1);
  762.    for (i = 0; i < num * 2; i++)
  763.       copy[i] = mesg.who[i];
  764.    for (i = 0; i < num; i++) {
  765.       mesg.who[2 * i] = copy[i];
  766.       mesg.who[2 * i + 1] = copy[num + i];
  767.    }
  768. }
  769.  
  770.  
  771. #define NAMECOL 12
  772. #define IDLECOL 25
  773. #define RANKCOL 33
  774. #define FLAGCOL 2
  775. #define GAMECOL 10
  776.  
  777.  
  778. int namesort(a, b)
  779. char **a, **b;
  780. {
  781.    int i;
  782.    i = strncasecmp(*a + NAMECOL, *b + NAMECOL, 11);
  783.    if (i < 0)
  784.       return -1;
  785.    if (i > 0)
  786.       return 1;
  787.    return 0;
  788. }
  789.  
  790.  
  791. /********************
  792.  * who sort functions modified by Edward Blair. 9-6-92 On ties, sort by name.
  793.  *        + addition of idlesort to sort on idle time.
  794.  ********************/
  795.  
  796. int gamesort(a, b)
  797. char **a, **b;
  798. {
  799.    int i;
  800.    if ((*a)[GAMECOL] != '-' && (*b)[GAMECOL] != '-') {
  801.       i = strncmp(*a + GAMECOL - 2, *b + GAMECOL - 2, 3);
  802.       return i ? (i < 0 ? -1 : 1) : namesort(a, b);
  803.    }
  804.    if ((*a)[GAMECOL] != '-')
  805.       return -1;
  806.    if ((*b)[GAMECOL] != '-')
  807.       return 1;
  808.    if ((*a)[FLAGCOL] != (*b)[FLAGCOL]) {
  809.       if ((*a)[FLAGCOL] == 'X')
  810.      return -1;
  811.       if ((*b)[FLAGCOL] == 'X')
  812.      return 1;
  813.       if ((*a)[FLAGCOL] == '!')
  814.      return 1;
  815.       if ((*b)[FLAGCOL] == '!')
  816.      return -1;
  817.    }
  818.    return ranksort(a, b);
  819. }
  820.  
  821.  
  822. int ranksort(a, b)
  823. char **a, **b;
  824. {
  825.    int i;
  826.    if ((*a)[RANKCOL] == '2')
  827.       return -1;
  828.    if ((*b)[RANKCOL] == '2')
  829.       return 1;
  830.    if ((*a)[RANKCOL] != (*b)[RANKCOL]) {
  831.       if ((*a)[RANKCOL] == '?')
  832.      return 1;
  833.       if ((*b)[RANKCOL] == '?')
  834.      return -1;
  835.       if ((*a)[RANKCOL] == 'R')
  836.      return 1;
  837.       if ((*b)[RANKCOL] == 'R')
  838.      return -1;
  839.       if ((*a)[RANKCOL] == 'k')
  840.      return 1;
  841.       if ((*b)[RANKCOL] == 'k')
  842.      return -1;
  843.       if ((*a)[RANKCOL] == 'd')
  844.      return 1;
  845.       if ((*b)[RANKCOL] == 'd')
  846.      return -1;
  847.       return namesort(a, b);
  848.    }
  849.    if ((*a)[RANKCOL] == 'R' || (*a)[RANKCOL] == '?')
  850.       return namesort(a, b);
  851.    i = atoi((*a) + RANKCOL - 2) - atoi((*b) + RANKCOL - 2);
  852.    if ((*a)[RANKCOL] == 'k')
  853.       i = -i;
  854.    if (i > 0)
  855.       return -1;
  856.    if (i < 0)
  857.       return 1;
  858.    return namesort(a, b);
  859. }
  860.  
  861. /*******************
  862.  * idlesort  decides whether a or b has been idle longer
  863.  *******************/
  864. int idlesort(a, b)
  865. char **a;
  866. char **b;
  867. {
  868.    int i;
  869.    /* first check the units letter (h,m,s) assume that we don't need to worry
  870.     * about d. */
  871.    if ((*a)[IDLECOL] != (*b)[IDLECOL]) {
  872.       if ((*a)[IDLECOL] == 'h')
  873.      return -1;
  874.       if ((*b)[IDLECOL] == 'h')
  875.      return 1;
  876.       if ((*a)[IDLECOL] == 'm')
  877.      return -1;
  878.       if ((*b)[IDLECOL] == 'm')
  879.      return 1;
  880.    }
  881.    i = atoi((*b) + IDLECOL - 2) - atoi((*a) + IDLECOL - 2);
  882.    if (i > 0)
  883.       return 1;
  884.    if (i < 0)
  885.       return -1;
  886.    return namesort(a, b);
  887. }
  888.  
  889.  
  890. int choosesort(first)
  891. char *first;
  892. {
  893.    if (!first)
  894.       return 1;
  895.    if (!strcmp(first, "name")) {
  896.       whosort = namesort;
  897.       return 0;
  898.    }
  899.    if (!strcmp(first, "rank")) {
  900.       whosort = ranksort;
  901.       return 0;
  902.    }
  903.    if (!strcmp(first, "game")) {
  904.       whosort = gamesort;
  905.       return 0;
  906.    }
  907.    if (!strcmp(first, "none")) {
  908.       whosort = 0;
  909.       return 0;
  910.    }
  911.    if (!strcmp(first, "idle")) {
  912.       whosort = idlesort;
  913.       return 0;
  914.    }
  915.    return 1;
  916. }
  917.  
  918.  
  919. restoregame()
  920. {
  921.    char str[30], str2[30];
  922.  
  923.    if (needrestore) {
  924.       if (bschange)
  925.      initboard(bschange);
  926.       restoremaxmoves();
  927.       endgame();
  928.       needrestore = 0;
  929.       sprintf(str, "%s (%s)", curgame.black, curgame.brank);
  930.       sprintf(str2, "%s (%s)", curgame.white, curgame.wrank);
  931.       boardtitle(str, str2);
  932.       highlight(0, 0, 0, -1, curgame.btime, curgame.bbyo,
  933.         curgame.wtime, curgame.wbyo);
  934.       displaygamenumber(ingame);
  935.    }
  936. }
  937.  
  938. main(argc, argv)
  939. int argc;
  940. char *argv[];
  941. {
  942.    char ch;
  943.    int ret;
  944.    puts("\tigc - Ascii Client version 0.60 by Adrian Mariano");
  945.    puts("   type 'helpigc' to get client help, 'help' for server help\n");
  946.    strcpy(prefix, "");
  947.    whosort = namesort;
  948.    readrc();
  949.    sethost(sitetable[0].site);
  950.    setport(sitetable[0].port);
  951.    doargs(argc, argv);
  952.    loc = local;
  953.    signal(SIGINT, handleterm);
  954.    signal(SIGTERM, handleterm);
  955.    signal(SIGHUP, handleterm);
  956.    signal(SIGTSTP, handletstp);
  957.    if (open_connection())
  958.       handleterm();
  959.    puts("Connection established.");
  960.    mesg.whocount = 0;
  961.    {
  962.       char *whoptr;
  963.       for (whoptr = &(mesg.whodata[0][0]), ret = 0; ret < MAXWHO; ret++, whoptr += 40)
  964.      mesg.who[ret] = whoptr;
  965.    }
  966.    initparser();
  967.    do {
  968.       if (boardon)
  969.      if (boardmode)
  970.         boardrefresh();
  971.      else
  972.         serverrefresh();
  973.       ret = getmessage(&mesg, 1);
  974.       if (ret < 0 && ret != KEY) {
  975.      if (boardon) {
  976.         endAscii();
  977.         boardon = 0;
  978.      }
  979.      puts("Connection closed by server.");
  980.      myexit(0);
  981.       }
  982.       if (ret > 0)
  983.      switch (mesg.id) {
  984.         case TOOMANY:
  985.            myexit(0);
  986.            printf("Too many players.  Sorry.\n");
  987.            break;
  988.         case QUITMESG:
  989.            if (boardon) {
  990.           endAscii();
  991.           boardon = 0;
  992.            }
  993.            puts(mesg.text);
  994.            break;
  995.         case ONSERVER:
  996.            printf("\nWarning: Client mode is not set on the IGS.  Setting client mode now.\n         The message of the day was not displayed.  Type 'help motd' to see it.\n         You have not been informed if you have messages.\n\n");
  997.  
  998.            break;
  999.         case BEEP:
  1000.            if (mesg.beep)
  1001.           dobeep();
  1002.            break;
  1003.         case MOVE:
  1004.            if (!boardon)
  1005.           puts("%Error: isolated move received");
  1006.            else {
  1007.           int i;
  1008.           restoregame();
  1009.           sethighlight(0);
  1010.           for (i = 0; i < mesg.movecount - 1; i++)
  1011.              makemove(mesg.moves[i].x, mesg.moves[i].y,
  1012.                   mesg.moves[i].movenum,
  1013.                   mesg.moves[i].color, mesg.btime,
  1014.                   mesg.bbyo, mesg.wtime, mesg.wbyo);
  1015.           sethighlight(1);
  1016.           if (mesg.movecount)
  1017.              makemove(mesg.moves[i].x, mesg.moves[i].y,
  1018.                   mesg.moves[i].movenum,
  1019.                   mesg.moves[i].color, mesg.btime,
  1020.                   mesg.bbyo, mesg.wtime, mesg.wbyo);
  1021.           curgame.bbyo = mesg.bbyo;
  1022.           curgame.btime = mesg.btime;
  1023.           curgame.wtime = mesg.wtime;
  1024.           curgame.wbyo = mesg.wbyo;
  1025.  
  1026.  
  1027.           setcursor(xcur, ycur);
  1028.           if (!justpeeked)
  1029.              setgame(mesg.gamenum);
  1030.           justpeeked = 0;
  1031.            }
  1032.            break;
  1033.         case UNDO:
  1034.            restoregame();
  1035.            if (!boardon)
  1036.           puts("%Error: isolated undo received");
  1037.            else {
  1038.           setgame(mesg.gamenum);
  1039.           undo();
  1040.           setcursor(xcur, ycur);
  1041.            }
  1042.            break;
  1043.         case SCOREUNDO:
  1044.            restoregame();
  1045.            if (endgame())
  1046.           putstr("%score undo error");
  1047.            else
  1048.           putstr("Scoring undone.");
  1049.            break;
  1050.         case LOAD:
  1051.            if (!startgame(mesg.gamenum))
  1052.           getmoves(mesg.gamenum);
  1053.            break;
  1054.         case MATCH:
  1055.            startgame(mesg.gamenum);
  1056.            break;
  1057.         case REMOVE:
  1058.            restoregame();
  1059.            removeGroup(mesg.x, mesg.y);
  1060.            setcursor(xcur, ycur);
  1061.            break;
  1062.         case SCORE:
  1063.            {
  1064.           char str[50];
  1065.           sprintf(str, "  %s (B): %g\n  %s (W): %g",
  1066.               mesg.black, mesg.bscore, mesg.white, mesg.wscore);
  1067.           putstr(str);
  1068.            }
  1069.            break;
  1070.         case STATUS:
  1071.         case LOOK:
  1072.            {
  1073.           int pris[2];
  1074.           char str[30], str2[30];
  1075.  
  1076.           if (mesg.boardsize > 19)
  1077.              putstr("%Boardsize too big.");
  1078.           else {
  1079.              needrestore = 1;
  1080.              bschange = 0;
  1081.              savemaxmoves();
  1082.              if (!boardon || boardsize != mesg.boardsize) {
  1083.             if (!boardon)
  1084.                needrestore = 0;
  1085.             else
  1086.                bschange = boardsize;
  1087.             initboard(mesg.boardsize);
  1088.             xcur = ycur = mesg.boardsize / 2;
  1089.             boardon = 1;
  1090.              }
  1091.              pris[0] = mesg.bcap;
  1092.              pris[1] = mesg.wcap;
  1093.              sprintf(str, "%s (%s)", mesg.black, mesg.brank);
  1094.              sprintf(str2, "%s (%s)", mesg.white, mesg.wrank);
  1095.              boardtitle(str, str2);
  1096.              highlight(0, 0, 0, -1, mesg.btime, mesg.bbyo,
  1097.                    mesg.wtime, mesg.wbyo);
  1098.              drawpris(pris);
  1099.              showboard(mesg.board);
  1100.              displaygamenumber(-2);
  1101.           }
  1102.            }
  1103.            break;
  1104.         case KIBITZ:{
  1105.           char s[300];
  1106.           sprintf(s, "%s: %s", mesg.kibitzer, mesg.kibitz);
  1107.           putstr(s);
  1108.            }
  1109.            break;
  1110.         case WHO:
  1111.            {
  1112.           char out[80 * 300];
  1113.           int i;
  1114.           if (whosort) {
  1115.              qsort(mesg.who, mesg.whocount, sizeof(char *), whosort);
  1116.              weave();
  1117.           }
  1118.           strcpy(out, mesg.whofirst);
  1119.           for (i = 0; i < mesg.whocount; i++) {
  1120.              strcat(out, i & 1 ? " | " : "\n");
  1121.              strcat(out, mesg.who[i]);
  1122.           }
  1123.           strcat(out, "\n");
  1124.           strcat(out, mesg.wholast);
  1125.           if (boardon)
  1126.              bigmess(mesg.lines, out);
  1127.           else
  1128.              putstr(out);
  1129.            }
  1130.            break;
  1131.         case STORED:
  1132.            if (!strlen(mesg.text))
  1133.           putstr("No stored games");
  1134.            else
  1135.           putstr(mesg.text);
  1136.            break;
  1137.         case CHKOMI:
  1138.            curgame.komi = mesg.mykomi;
  1139.            showkomi(curgame.komi);
  1140.         case INFO:
  1141.            if (strstr(mesg.text, "Removing")) {
  1142.           observing = 0;
  1143.           setgame(-1);
  1144.           putstr(mesg.text);
  1145.            } else if (mesg.lines > 1 && boardon)
  1146.           bigmess(mesg.lines, mesg.text);
  1147.            else if (strlen(mesg.text))
  1148.           putstr(mesg.text);
  1149.            break;
  1150.         case PROMPT:
  1151.            if (ingame != -1 && mesg.prompttype == 5) {
  1152.           setgame(-1);
  1153.           observing = 0;
  1154.            }
  1155.            break;
  1156.         case SAY:
  1157.            if (saybeep)
  1158.           dobeep();
  1159.            putstr(mesg.text);
  1160.            break;
  1161.         case TELL:
  1162.            if (tellbeep)
  1163.           dobeep();
  1164.            putstr(mesg.text);
  1165.            break;
  1166.         case 0:
  1167.            break;
  1168.         default:
  1169.            if (mesg.lines > 1 && boardon)
  1170.           bigmess(mesg.lines, mesg.text);
  1171.            else if (strlen(mesg.text))
  1172.           putstr(mesg.text);
  1173.            break;
  1174.      }
  1175.       if (ret == KEY) {
  1176.      ret = read(fileno(stdin), &ch, 1);
  1177.      if (ch == '\r')
  1178.         ch = '\n';
  1179.      if (ch == 'L' - 64 && boardon)
  1180.         redraw();
  1181.      else if (ch == 27 && boardon)
  1182.         switchmode();
  1183.      else if (boardmode)
  1184.         doboardmode(ch);
  1185.      else
  1186.         doservermode(ch);
  1187.       }
  1188.    } while (1);
  1189.    handleterm();
  1190. }
  1191.  
  1192.  
  1193. switchmode()
  1194. {
  1195.    boardmode = !boardmode;
  1196.    if (boardmode)
  1197.       setcursor(xcur, ycur);
  1198. }
  1199.  
  1200.  
  1201. static char *nomoves = "%no moves recorded";
  1202.  
  1203. doboardmode(ch)
  1204. char ch;
  1205. {
  1206.    char movestr[10];
  1207.    switch (ch) {
  1208.       case ',':
  1209.      restoregame();
  1210.      if (backward(1))
  1211.         putstr(nomoves);
  1212.      break;
  1213.       case '.':
  1214.      restoregame();
  1215.      if (forward(1))
  1216.         putstr(nomoves);
  1217.      break;
  1218.       case '<':
  1219.      restoregame();
  1220.      if (backward(10))
  1221.         putstr(nomoves);
  1222.      break;
  1223.       case '>':
  1224.      restoregame();
  1225.      if (forward(10))
  1226.         putstr(nomoves);
  1227.      break;
  1228.       case 's':
  1229.      restoregame();
  1230.      if (beginninggame())
  1231.         putstr(nomoves);
  1232.      break;
  1233.       case 'e':
  1234.      restoregame();
  1235.      if (endgame())
  1236.         putstr(nomoves);
  1237.      break;
  1238.       case '1':
  1239.       case 'b':
  1240.      if (++ycur == boardsize)
  1241.         ycur = 0;
  1242.      if (!xcur--)
  1243.         xcur = boardsize - 1;
  1244.      break;
  1245.       case '3':
  1246.       case 'n':
  1247.      if (++ycur == boardsize)
  1248.         ycur = 0;
  1249.      if (++xcur == boardsize)
  1250.         xcur = 0;
  1251.      break;
  1252.       case '7':
  1253.       case 'y':
  1254.      if (!xcur--)
  1255.         xcur = boardsize - 1;
  1256.      if (!ycur--)
  1257.         ycur = boardsize - 1;
  1258.      break;
  1259.       case '9':
  1260.       case 'u':
  1261.      if (!ycur--)
  1262.         ycur = boardsize - 1;
  1263.      if (++xcur == boardsize)
  1264.         xcur = 0;
  1265.      break;
  1266.       case 'B' - 64:
  1267.       case '4':
  1268.       case 'h':
  1269.  
  1270.      if (!xcur--)
  1271.         xcur = boardsize - 1;
  1272.      break;
  1273.       case 'P' - 64:
  1274.       case '8':
  1275.       case 'k':
  1276.      if (!ycur--)
  1277.         ycur = boardsize - 1;
  1278.      break;
  1279.       case 'N' - 64:
  1280.       case '2':
  1281.       case 'j':
  1282.      if (++ycur == boardsize)
  1283.         ycur = 0;
  1284.      break;
  1285.       case 'F' - 64:
  1286.       case '6':
  1287.       case 'l':
  1288.      if (++xcur == boardsize)
  1289.         xcur = 0;
  1290.      break;
  1291.       case 'c':
  1292.      unmark();
  1293.      break;
  1294.       case '\n':
  1295.       case '\r':
  1296.       case ' ':
  1297.       case '0':
  1298.      sprintf(movestr, "%c%d\n", xcur + 'A' + (xcur + 'A' >= 'I' ? 1 : 0),
  1299.          boardsize - ycur);
  1300.      sendstr(movestr);
  1301.      break;
  1302.    }
  1303.    setcursor(xcur, ycur);
  1304. }
  1305.  
  1306.  
  1307.  
  1308. process(comm, dopre)
  1309. char *comm;
  1310. int dopre;
  1311. {
  1312.    char *first;
  1313.    char save[1000];
  1314.  
  1315.    strcpy(save, comm);
  1316.    first = strtok(comm, " \n\t");
  1317.    if (!first)
  1318.       return;
  1319.    if (!strcmp(first, "helpigc"))
  1320.       help();
  1321.    else if (!strcmp(first, "peek") || !strcmp(first, "moves")) {
  1322.       first = strtok(NULL, " \t\n");
  1323.       if (first) {
  1324.      if (!observing && ingame != -1)
  1325.         putstr("%Can't observe while playing");
  1326.      else if (observing && ingame == atoi(first))
  1327.         unobserve();
  1328.      else if (peekgame(atoi(first)))
  1329.         putstr("%No such game");
  1330.       }
  1331.    } else if (!strcmp(first, "observe") || !strcmp(first, "ob")) {
  1332.       first = strtok(NULL, " \t\n");
  1333.       if (first) {
  1334.      if (!observing && ingame != -1)
  1335.         putstr("%Can't observe while playing");
  1336.      else if (observing && ingame == atoi(first))
  1337.         unobserve();
  1338.      else if (observegame(atoi(first)))
  1339.         putstr("%No such game");
  1340.       }
  1341.    } else if (!strcmp(first, "unobserve") || !strcmp(first, "unob")) {
  1342.       if (observing)
  1343.      unobserve();
  1344.       else
  1345.      putstr("%Not observing");
  1346.    } else if (!strcmp(first, "load")) {
  1347.       first = strtok(NULL, " \n\t");
  1348.       if (first)
  1349.      loadgame(first);
  1350.    } else if (!strcmp(first, "chars")) {
  1351.       first = strtok(NULL, " \n\t");
  1352.       if (first) {
  1353.      setchars(first);
  1354.      if (boardon) {
  1355.         reinitboard(boardsize);
  1356.         endgame();
  1357.      }
  1358.       }
  1359.    } else if (!strcmp(first, "restore")) {
  1360.       if (!needrestore)
  1361.      putstr("%no game to restore");
  1362.       restoregame();
  1363.    } else if (!strcmp(first, "sort")) {
  1364.       first = strtok(NULL, " \t\n");
  1365.       if (choosesort(first))
  1366.      putstr("%Unknown sorting method");
  1367.    } else if (!strcmp(first, "border")) {
  1368.       first = strtok(NULL, " \t");
  1369.       if (!first)
  1370.      setborder(' ');
  1371.       else
  1372.      setborder(*first);
  1373.       if (boardon) {
  1374.      reinitboard(boardsize);
  1375.      endgame();
  1376.       }
  1377.    } else if (!strcmp(first, "inverse")) {
  1378.       setinverse(1);
  1379.       if (boardon) {
  1380.      reinitboard(boardsize);
  1381.      endgame();
  1382.       }
  1383.    } else if (!strcmp(first, "noinverse")) {
  1384.       setinverse(0);
  1385.       if (boardon) {
  1386.      reinitboard(boardsize);
  1387.      endgame();
  1388.       }
  1389.    } else if (!strcmp(first, "noinvedge")) {
  1390.       setinverseborder(0);
  1391.       if (boardon) {
  1392.      reinitboard(boardsize);
  1393.      endgame();
  1394.       }
  1395.    } else if (!strcmp(first, "noedgemarks")) {
  1396.       setedgemark(0);
  1397.       if (boardon) {
  1398.      reinitboard(boardsize);
  1399.      endgame();
  1400.       }
  1401.    } else if (!strcmp(first, "edgemarks")) {
  1402.       setedgemark(1);
  1403.       if (boardon) {
  1404.      reinitboard(boardsize);
  1405.      endgame();
  1406.       }
  1407.    } else if (!strcmp(first, "piecemarks")) {
  1408.       setpiecemark(1);
  1409.       if (boardon) {
  1410.      reinitboard(boardsize);
  1411.      endgame();
  1412.       }
  1413.    } else if (!strcmp(first, "nopiecemarks")) {
  1414.       setpiecemark(0);
  1415.       if (boardon) {
  1416.      reinitboard(boardsize);
  1417.      endgame();
  1418.       }
  1419.    } else if (!strcmp(first, "invedge")) {
  1420.       setinverseborder(1);
  1421.       if (boardon) {
  1422.      reinitboard(boardsize);
  1423.      endgame();
  1424.       }
  1425.    } else if (!strcmp(first, "prefix")) {
  1426.       first = strtok(NULL, "\n");
  1427.       if (!first)
  1428.      strcpy(prefix, "");
  1429.       else {
  1430.      strncpy(prefix, first, 19);
  1431.      prefix[20] = 0;
  1432.       }
  1433.  
  1434.       if (boardon)
  1435.      showprefix(prefix);
  1436.       else
  1437.      printf("Prefix '%s'\n", prefix);
  1438.    } else if (!strcmp(first, "user")) {
  1439.       first = strtok(NULL, " \t\n");
  1440.       {
  1441.      int i;
  1442.      int found;
  1443.      found = 0;
  1444.      for (i = 0; i < mesg.whocount; i++) {
  1445.         if (!strncmp(mesg.who[i] + NAMECOL, first, strlen(first)) &&
  1446.         mesg.who[i][NAMECOL + strlen(first)] == ' ') {
  1447.            putstr(mesg.who[i]);
  1448.            found = 1;
  1449.         }
  1450.      }
  1451.      if (!found)
  1452.         putstr("User not found in last who");
  1453.       }
  1454.    } else if (!strcmp(first, "saybeep"))
  1455.       saybeep = 1;
  1456.    else if (!strcmp(first, "nosaybeep"))
  1457.       saybeep = 0;
  1458.    else if (!strcmp(first, "tellbeep"))
  1459.       tellbeep = 1;
  1460.    else if (!strcmp(first, "notellbeep"))
  1461.       tellbeep = 0;
  1462.    else if (!strcmp(first, "beeps")) {
  1463.       first = strtok(NULL, " \t");
  1464.       if (first)
  1465.      beepcount = atoi(first);
  1466.    } else if (!strcmp(first, "clear")) {
  1467.       if (!boardon)
  1468.      putstr("%Cannot clear.");
  1469.       else
  1470.      clearserver();
  1471.    } else if (!strcmp(first, "noboard")) {
  1472.       if (boardon) {
  1473.      if (ingame != -1) {
  1474.         putstr("Board in use.  Cannot remove.");
  1475.      } else {
  1476.         boardon = 0;
  1477.         boardmode = 0;
  1478.         endAscii();
  1479.      }
  1480.       } else
  1481.      putstr("%No board to remove.");
  1482.    } else if (!strcmp(first, "goto")) {
  1483.       if (boardon) {
  1484.      first = strtok(NULL, " \t");
  1485.      if (first)
  1486.         construct(atoi(first));
  1487.       } else
  1488.      putstr("%no board");
  1489.    } else {
  1490.       if (dopre)
  1491.      sendstr(prefix);
  1492.       sendstr(save);
  1493.    }
  1494. }
  1495.  
  1496.  
  1497. int notfirst = 0;
  1498.  
  1499. doservermode(ch)
  1500. char ch;
  1501. {
  1502.    *loc = ch;
  1503.    *(loc + 1) = 0;
  1504.    if (ch < ' ' && ch != ('U' - 64) && ch != '\b' && ch != '\n')
  1505.       return;
  1506.    if (boardon) {
  1507.       if (*loc == '\b' || *loc == '\177') {
  1508.      if (strlen(local) > 1) {
  1509.         deletechar(strlen(local) - 2);
  1510.         loc -= 2;
  1511.      } else
  1512.         loc--;
  1513.       } else if (*loc == 'U' - 64) {
  1514.      loc = local;
  1515.      clrline();
  1516.      return;
  1517.       } else if (strlen(local) > linesize()) {
  1518.      if (!notfirst)
  1519.         sendstr(prefix);
  1520.      sendstr(local);
  1521.      loc = local;
  1522.      notfirst = 1;
  1523.      clrline();
  1524.      putstr(local);
  1525.      return;
  1526.       } else
  1527.      addcharline(strlen(local) - 1, *loc);
  1528.    }
  1529.    if (*loc == '\n') {
  1530.       loc++;
  1531.       *loc = 0;
  1532.       if (boardon) {
  1533.      addstring(local);
  1534.       }
  1535.       if (notfirst)
  1536.      sendstr(local);
  1537.       else if (local[0] == '!')
  1538.      process(local + 1, 0);
  1539.       else if (strlen(prefix)) {
  1540.      sendstr(prefix);
  1541.      sendstr(local);
  1542.       } else
  1543.      process(local, 1);
  1544.       if (boardon)
  1545.      clrline();
  1546.       notfirst = 0;
  1547.       loc = local;
  1548.    } else
  1549.       loc++;
  1550. }
  1551. SHAR_EOF
  1552. fi
  1553. if test -f 'parse.c'
  1554. then
  1555.     echo shar: "will not over-write existing file 'parse.c'"
  1556. else
  1557. cat << \SHAR_EOF > 'parse.c'
  1558. #include "igc.h"
  1559. #include <stdio.h>
  1560. #include <string.h>
  1561. #include <sys/types.h>
  1562. #include "numbers.h"
  1563.  
  1564. extern char *getloginname();
  1565. extern char *getpassword();
  1566. int loggedon;
  1567. int repeatpass, repeatlogin;
  1568.  
  1569. #ifdef STRSTR
  1570. char *strstr();
  1571. #endif
  1572.  
  1573. #ifdef STRTOL
  1574. long strtol();
  1575. #endif
  1576.  
  1577. char *Prompts[] =
  1578. {
  1579.    "Login: ",
  1580.    "Password: ",
  1581.    "Password: ",
  1582.    "Enter Your Password Again: ",
  1583.    "Enter your e-mail address (None): ",
  1584.    "#> ",
  1585.    "#> ",
  1586.    "Enter Dead Group: ",
  1587.    "#> ",
  1588.    "#> ",
  1589. };
  1590.  
  1591.  
  1592. initparser()
  1593. {
  1594.    loggedon = 0;
  1595.    repeatpass = 0;
  1596.    repeatlogin = 0;
  1597. }
  1598.  
  1599.  
  1600. DoState(s)
  1601. char *s;
  1602. {
  1603.    if (strncmp(s, Prompts[LOGON], strlen(Prompts[LOGON])) == 0)
  1604.       return LOGON;
  1605.    if (strncmp(s, "1 1", 3) == 0)
  1606.       return PASSWORD;
  1607.    if (strncmp(s, "1 0", 3) == 0)
  1608.       return LOGON;
  1609.    if (strncmp(s, Prompts[PASSWORD], strlen(Prompts[PASSWORD])) == 0)
  1610.       return PASSWORD;
  1611.    if (strncmp(s, Prompts[PASSWD_NEW], strlen(Prompts[PASSWD_NEW])) == 0)
  1612.       return PASSWD_NEW;
  1613.    if (strncmp(s, Prompts[PASSWD_CONFIRM],
  1614.            strlen(Prompts[PASSWD_CONFIRM])) == 0)
  1615.       return PASSWD_CONFIRM;
  1616.    if (strncmp(s, Prompts[WAITING], strlen(Prompts[WAITING])) == 0)
  1617.       return WAITING;
  1618.    if (!strncmp(s, "Too many players, sorry", 23) ||
  1619.        !strncmp(s, "Sorry, the server is full", 24))
  1620.       return TOOMANY;
  1621.    return -1;
  1622. }
  1623.  
  1624. static long appending = 0;
  1625.  
  1626. int getmessage(mess, checkstdin)
  1627. message *mess;
  1628. int checkstdin;
  1629. {
  1630.    char mesg[2000];
  1631.    int ret;
  1632.    char *textpart;
  1633.  
  1634.    ret = pollserver(mesg, checkstdin);
  1635.    if (ret <= 0)
  1636.       return ret;
  1637.    switch (DoState(mesg)) {
  1638.       case PASSWD_NEW:
  1639.       case PASSWD_CONFIRM:
  1640.       case PASSWORD:
  1641.      sendstr(getpassword(repeatpass++));
  1642.      sendstr("\n");
  1643.      break;
  1644.       case WAITING:
  1645.      sendstr("toggle client true\n");
  1646.      mess->id = ONSERVER;
  1647.      loggedon = 1;
  1648.      return 1;
  1649.       case TOOMANY:
  1650.      mess->id = TOOMANY;
  1651.      return 1;
  1652.       case LOGON:
  1653.      {
  1654.         int needlogin;
  1655.         needlogin = 1;
  1656.         do {
  1657.            if (needlogin == 1) {
  1658.           sendstr(getloginname(repeatlogin++));
  1659.           sendstr("\n");
  1660.           needlogin = -1;
  1661.            }
  1662.            ret = pollserver(mesg, 0);
  1663.            if (ret < 0)
  1664.           return ret;
  1665.            if (!strncmp(mesg, "Password:", 9) || (!strncmp(mesg, "1 1", 3)))
  1666.           needlogin = 0;
  1667.            else if (!strncmp(mesg, "Sorry", 5)) {
  1668.           puts(mesg);
  1669.           if (!strncmp(mesg, "Sorry, the server is full", 24)) {
  1670.              mess->id = TOOMANY;
  1671.              return 1;
  1672.           }
  1673.           return 0;
  1674.            } else if (strlen(mesg) > 2 && strncmp(mesg, "Login", 5))
  1675.           puts(mesg);
  1676.         } while (needlogin);
  1677.         sendstr(getpassword(repeatpass++));
  1678.         sendstr("\n");
  1679.         do {
  1680.            ret = pollserver(mesg, 0);
  1681.            if (ret < 0)
  1682.           return ret;
  1683.            if (!strncmp(mesg, "Enter", 5)) {
  1684.           sendstr(getpassword(repeatpass++));
  1685.           sendstr("\n");
  1686.            }
  1687.            if (!strncmp(mesg, "9 File", 6))
  1688.           needlogin = -1;
  1689.            if (!strncmp(mesg, "To get", 6))
  1690.           needlogin = 1;
  1691.            if (!strncmp(mesg, "#>", 2)) {
  1692.           sendstr("toggle client true\n");
  1693.           mess->id = ONSERVER;
  1694.           loggedon = 1;
  1695.           return 1;
  1696.            }
  1697.            if (!strncmp(mesg, "Invalid", 7)) {
  1698.           puts(mesg);
  1699.           needlogin = 1;
  1700.            }
  1701.         } while (!needlogin);
  1702.  
  1703.         if (needlogin > 0)
  1704.            break;
  1705.      }            /* intentional fall through occurs here */
  1706.       default:
  1707.      mess->id = strtol(mesg, &textpart, 10);
  1708.      textpart++;
  1709.      if (mess->id == 2 && (strstr(textpart, "Game")
  1710.                    || strstr(textpart, "min")))
  1711.         mess->id = TIMEREP;
  1712.      if (appending == -1) {
  1713.         if (mess->id && !strncmp(textpart, "File", 4)) {
  1714.            appending = 0;
  1715.            if (mess->id == INFO &&
  1716.            !strncmp(mess->text, "~~~~~~~~~~~~~~~~~~~~~", 21))
  1717.           mess->id = QUITMESG;
  1718.            return 1;
  1719.         }
  1720.         if (strlen(mess->text)) {
  1721.            strcat(mess->text, "\n");
  1722.            mess->lines++;
  1723.         } {
  1724.            int len;
  1725.            char *pt;
  1726.            len = strlen(mesg);
  1727.            pt = mesg;
  1728.            while (len > 0) {
  1729.           strncat(mess->text, pt, 79);
  1730.           len -= 79;
  1731.           pt += 79;
  1732.           if (len > 0) {
  1733.              mess->lines++;
  1734.              strcat(mess->text, "\n");
  1735.           }
  1736.            }
  1737.         }
  1738.         return 0;
  1739.      }
  1740.      if (mess->id == PROMPT) {
  1741.         if (*textpart == '5' && !loggedon)
  1742.            loggedon = 1;
  1743.         if (appending) {
  1744.            mess->id = appending;
  1745.            appending = 0;
  1746.            return 1;
  1747.         }
  1748.         mess->prompttype = atoi(textpart);
  1749.      }
  1750.      if (!strcmp(textpart, "File")) {
  1751.         appending = -1;
  1752.         strcpy(mess->text, "");
  1753.         mess->lines = 1;
  1754.         return 0;
  1755.      }
  1756.      if (mess->id == BEEP) {
  1757.         mess->beep = (*textpart == 7);
  1758.      }
  1759.      if (mess->id == KIBITZ) {
  1760.         if (parsekibitz(textpart, mess))
  1761.            return 0;
  1762.      }
  1763.      if (mess->id == UNDO)
  1764.         if (ret = parseundo(textpart, &(mess->gamenum))) {
  1765.            if (ret < 0)
  1766.           return ret;
  1767.            return 0;
  1768.         }
  1769.      if (mess->id == TRANSLATE) {
  1770.         if (appending) {
  1771.            strcat(mess->text, "\n");
  1772.            strcat(mess->text, textpart);
  1773.            mess->lines++;
  1774.         } else {
  1775.            strcpy(mess->text, textpart);
  1776.            mess->lines = 1;
  1777.         }
  1778.         appending = TRANSLATE;
  1779.         return 0;
  1780.      }
  1781.      if (mess->id == MOVE) {
  1782.         appending = MOVE;
  1783.         parsemove(textpart, mess);
  1784.         return 0;
  1785.      }
  1786.      if (mess->id == WHO)
  1787.         return parsewho(mess, textpart);
  1788.      if (mess->id == GAMES) {
  1789.         appending = GAMES;
  1790.         parsegame(mess, textpart);
  1791.         return 0;
  1792.      }
  1793.      if (mess->id == STATUS)
  1794.         return parsestatus(mess, textpart);
  1795.      strcpy(mess->text, textpart);
  1796.      mess->lines = 1;
  1797.      if (mess->id == ERROR &&
  1798.          !strcmp("Game not found.", textpart)) {
  1799.         mess->id = GAMES;
  1800.         mess->gamecount = 0;
  1801.         return 1;
  1802.      }
  1803.      if (mess->id == INFO)
  1804.         if (ret = parseinfo(textpart, mess))
  1805.            return ret;
  1806.      return 1;
  1807.    }
  1808.    return 0;
  1809.  
  1810. }
  1811.  
  1812. #ifdef STRTOL
  1813. long strtol(text, new, dum)
  1814. char *text;
  1815. char **new;
  1816. int dum;
  1817. {
  1818.    long retu;
  1819.    retu = atol(text);
  1820.    for (*new = text; *new && **new <= '9' && **new >= '0'; (*new)++);
  1821.    return retu;
  1822. }
  1823. #endif
  1824.  
  1825.  
  1826.  
  1827. #ifdef STRSTR
  1828. char *strstr(s1, s2)
  1829. char *s1, *s2;
  1830. {
  1831.    register char *temp;
  1832.    int len;
  1833.  
  1834.    temp = s1;
  1835.    len = strlen(s2);
  1836.    while (temp = strchr(temp, *s2)) {
  1837.       if (!strncmp(temp, s2, len))
  1838.      return temp;
  1839.       else
  1840.      temp++;
  1841.    }
  1842.    return NULL;
  1843. }
  1844. #endif
  1845.  
  1846.  
  1847.  
  1848. int parsestatus(mesg, s)
  1849. message *mesg;
  1850. char *s;
  1851. {
  1852.    int line, i;
  1853.    char wflag, bflag;
  1854.  
  1855.    if (1 == sscanf(s, " %d:", &line)) {
  1856.       mesg->boardsize = line + 1;
  1857.       for (i = 0, s += 4; *s; i++, s++)
  1858.      switch (*s) {
  1859.         case S_BLACK:
  1860.            mesg->board[line][i] = BLACK;
  1861.            break;
  1862.         case S_WHITE:
  1863.            mesg->board[line][i] = WHITE;
  1864.            break;
  1865.         case S_EMPTY:
  1866.         case S_HOSHI:
  1867.            mesg->board[line][i] = EMPTY;
  1868.            break;
  1869.         case S_WTERR:
  1870.            mesg->board[line][i] = WTERR;
  1871.            break;
  1872.         case S_BTERR:
  1873.            mesg->board[line][i] = BTERR;
  1874.            break;
  1875.         case S_DAME:
  1876.            mesg->board[line][i] = DAME;
  1877.            break;
  1878.      }
  1879.       if (i == line + 1)
  1880.      return 1;
  1881.    } else {
  1882.       if (mesg->wnext) {
  1883.      sscanf(s, "%[^ ] %[^ ] %d %d %d %c %f %d",
  1884.         mesg->white, mesg->wrank, &(mesg->wcap), &(mesg->wtime),
  1885.         &(mesg->wbyo), &wflag, &(mesg->mykomi), &(mesg->hcap));
  1886.      if (wflag == 'F')
  1887.         mesg->wbyo = -1;
  1888.       } else {
  1889.      sscanf(s, "%[^ ] %[^ ] %d %d %d %c %f %d",
  1890.         mesg->black, mesg->brank, &(mesg->bcap), &(mesg->btime),
  1891.         &(mesg->bbyo), &bflag, &(mesg->mykomi), &(mesg->hcap));
  1892.      if (bflag == 'F')
  1893.         mesg->bbyo = -1;
  1894.       }
  1895.       mesg->wnext = !mesg->wnext;
  1896.    }
  1897.    return 0;
  1898. }
  1899.  
  1900.  
  1901. int parsewho(mesg, str)
  1902. message *mesg;
  1903. char *str;
  1904. {
  1905.    if (!strncmp(str, " Info", 5)) {
  1906.       mesg->whocount = 0;
  1907.       strcpy(mesg->text, str);
  1908.       mesg->lines = 1;
  1909.       strcpy(mesg->whofirst, str);
  1910.    } else {
  1911.       strcat(mesg->text, "\n");
  1912.       strcat(mesg->text, str);
  1913.       mesg->lines++;
  1914.       if (strstr(str, "******")) {
  1915.      strcpy(mesg->wholast, str);
  1916.      return 1;
  1917.       } else {
  1918.      strncpy(mesg->who[mesg->whocount++], str, 34);
  1919.      if (strlen(str) > 40)
  1920.         strncpy(mesg->who[mesg->whocount++], str + 37, 34);
  1921.       }
  1922.    }
  1923.    return 0;
  1924. }
  1925.  
  1926.  
  1927. parsegame(mesg, str)
  1928. message *mesg;
  1929. char *str;
  1930. {
  1931.    int fieldcount;
  1932.    char *br, *wr, blackrank[10], whiterank[10];
  1933.    if (str[1] == '#') {
  1934.       mesg->gamecount = 0;
  1935.       strcpy(mesg->text, str);
  1936.       mesg->lines = 1;
  1937.    } else {
  1938.       strcat(mesg->text, "\n");
  1939.       strcat(mesg->text, str);
  1940.       mesg->lines++;
  1941.  
  1942.       /* hacked for systems that don't like %[^]] */
  1943.       for (br = str; *br; br++)
  1944.      if (*br == ']')
  1945.         *br = '!';
  1946.       fieldcount = sscanf(str, "[%3d!%12s [%[^!]! vs.%12s [%[^!]! (%3d %d %d %f)\n",
  1947.               &(mesg->gamelist[mesg->gamecount].gnum),
  1948.               mesg->gamelist[mesg->gamecount].white,
  1949.               whiterank,
  1950.               mesg->gamelist[mesg->gamecount].black,
  1951.               blackrank,
  1952.               &(mesg->gamelist[mesg->gamecount].mnum),
  1953.               &(mesg->gamelist[mesg->gamecount].bsize),
  1954.               &(mesg->gamelist[mesg->gamecount].hcap),
  1955.               &(mesg->gamelist[mesg->gamecount].komi));
  1956.       br = blackrank;
  1957.       wr = whiterank;
  1958.       if (*br == ' ')
  1959.      br++;
  1960.       if (*wr == ' ')
  1961.      wr++;
  1962.       strcpy(mesg->gamelist[mesg->gamecount].wrank, wr);
  1963.       strcpy(mesg->gamelist[mesg->gamecount].brank, br);
  1964.       if (fieldcount == 9)
  1965.      (mesg->gamecount)++;
  1966.    }
  1967. }
  1968.  
  1969.  
  1970. int parseinfo(s, mess)
  1971. char *s;
  1972. message *mess;
  1973. {
  1974.    int ret;
  1975.    extern int boardsize;
  1976.    int row;
  1977.    char col;
  1978.    char text[100];
  1979.    if (1 == sscanf(s, "Set the komi to %f.", &(mess->mykomi))) {
  1980.       mess->id = CHKOMI;
  1981.       return 0;
  1982.    }
  1983.    if (2 == sscanf(s, "Match [%dx%d]", &ret, &ret))
  1984.       return 0;
  1985.    if (1 == sscanf(s, "Match [%d]", &(mess->gamenum))) {
  1986.       mess->id = MATCH;
  1987.       return 0;
  1988.    }
  1989.    if (1 == sscanf(s, "Creating match [%d]", &(mess->gamenum))) {
  1990.       mess->id = MATCH;
  1991.       return 0;
  1992.    }
  1993.    if (2 == sscanf(s, "Removing @ %c%d", &col, &row)) {
  1994.  
  1995.       if (col > 'I')
  1996.      col--;
  1997.       mess->x = col - 'A';
  1998.       mess->y = boardsize - row;
  1999.       mess->id = REMOVE;
  2000.       return 0;
  2001.    }
  2002.    if (!strncmp(s, "Board is restored", 17)) {
  2003.       mess->id = SCOREUNDO;
  2004.       return 0;
  2005.    }
  2006.    if (strstr(s, "has restored your old game.")) {
  2007.       mess->id = LOAD;
  2008.       ret = pollserver(text, 0);
  2009.       if (ret < 0)
  2010.      return ret;
  2011.       ret = pollserver(text, 0);
  2012.       if (ret < 0)
  2013.      return ret;
  2014.       ret = sscanf(text, "%*d Game %d: %*[^(](%d %d %d) vs %*[^(](%d %d %d)",
  2015.            &(mess->gamenum), &(mess->bcap), &(mess->btime),
  2016.            &(mess->bbyo), &(mess->wcap), &(mess->wtime), &(mess->wbyo)
  2017.      );
  2018.       ret = pollserver(text, 0);
  2019.       if (ret < 0)
  2020.      return ret;
  2021.       return 0;
  2022.    }
  2023.    return 0;
  2024. }
  2025.  
  2026.  
  2027. int parseundo(s, gamenum)
  2028. char *s;
  2029. int *gamenum;
  2030. {
  2031.    char mes[2000];
  2032.    int count;
  2033.    int bogus2, ret;
  2034.    char bogus1;
  2035.    count = sscanf(s, "%*[^ ] undid the last move (%c%d).", &bogus1, &bogus2);
  2036.    if (count == 2) {
  2037.       ret = pollserver(mes, 0);
  2038.       if (ret < 0)
  2039.      return ret;
  2040.       ret = pollserver(mes, 0);
  2041.       if (ret < 0)
  2042.      return ret;
  2043.       sscanf(mes, "%*d Game %d", gamenum);
  2044.       ret = pollserver(mes, 0);
  2045.       if (ret < 0)
  2046.      return ret;
  2047.       return 0;
  2048.    }
  2049.    if (1 == sscanf(s, "%*[^ ] undid the last move (Handicap %d).", &bogus2))
  2050.       return 0;
  2051.    count = sscanf(s, "Undo in game %d", gamenum);
  2052.    if (count != 1)
  2053.       return 1;            /* extra line */
  2054.    return 0;
  2055. }
  2056.  
  2057.  
  2058. int parsekibitz(s, mess)
  2059. char *s;
  2060. message *mess;
  2061. {
  2062.    if (1 == sscanf(s, "Kibitz %[^:]", mess->kibitzer))
  2063.       return 1;
  2064.    while (*s == ' ')
  2065.       s++;
  2066.    strcpy(mess->kibitz, s);
  2067.    return 0;
  2068.  
  2069. }
  2070.  
  2071.  
  2072. parsemove(s, mess)
  2073. char *s;
  2074. message *mess;
  2075. {
  2076.    int mc, y, mv;
  2077.    char c, col;
  2078.    extern int boardsize;
  2079.  
  2080.    if (!strncmp(s, "Game ", 5)) {
  2081.       sscanf(s, "Game %d: %*[^(](%d %d %d) vs %*[^(](%d %d %d)",
  2082.          &(mess->gamenum), &(mess->wcap), &(mess->wtime),
  2083.          &(mess->wbyo), &(mess->bcap),
  2084.          &(mess->btime), &(mess->bbyo));
  2085.       mess->movecount = 0;
  2086.       return;
  2087.    }
  2088.    mc = sscanf(s, "%3d(%c): %c%d", &mv, &c, &col, &y);
  2089.    if (mc == 3) {
  2090.       if (3 == sscanf(s, "%3d(%c): Handicap %d", &mv, &c, &mc)) {
  2091.      mess->moves[mess->movecount].x = mess->moves[mess->movecount].y = mc + 100;
  2092.      mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2093.      mess->moves[mess->movecount].movenum = mv + 1;
  2094.      mess->movecount++;
  2095.      return;
  2096.       }
  2097.       if (2 == sscanf(s, "%3d(%c): Pass", &mv, &c)) {
  2098.      mess->moves[mess->movecount].x = mess->moves[mess->movecount].y = 99;
  2099.      mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2100.      mess->moves[mess->movecount].movenum = mv + 1;
  2101.      mess->movecount++;
  2102.      return;
  2103.       }
  2104.    }
  2105.    if (col > 'I')
  2106.       col--;
  2107.    mess->moves[mess->movecount].x = col - 'A';
  2108.    mess->moves[mess->movecount].y = boardsize - y;
  2109.    mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2110.    mess->moves[mess->movecount].movenum = mv + 1;
  2111.    mess->movecount++;
  2112. }
  2113.  
  2114.  
  2115. int doneline(inbuf, inptr)
  2116. char *inbuf;
  2117. int inptr;
  2118. {
  2119.    return !loggedon &&
  2120.       (inptr > 0 && inbuf[inptr - 1] == ' ') &&
  2121.       ((inptr > 1 && inbuf[inptr - 2] == ':') ||
  2122.        (inptr > 2 && inbuf[inptr - 2] == '>' && inbuf[inptr - 3] == '#'));
  2123. }
  2124. SHAR_EOF
  2125. fi
  2126. if test -f 'ascii.c'
  2127. then
  2128.     echo shar: "will not over-write existing file 'ascii.c'"
  2129. else
  2130. cat << \SHAR_EOF > 'ascii.c'
  2131.  
  2132. #include <curses.h>
  2133.  
  2134. #define piece char
  2135.  
  2136. #define TOP 2
  2137. #define LEFT 3
  2138. #define RIGHT 79
  2139. #define min(a,b) (((a)<(b))?(a):(b))
  2140. #define TITLEX 6
  2141. #define HIGHLIGHT 23
  2142.  
  2143. #define   CHAR_NOTHING 0
  2144. #define   CHAR_BLACK 1
  2145. #define   CHAR_WHITE 2
  2146. #define   CHAR_DAME 3
  2147. #define   CHAR_BLACKTERR 4
  2148. #define   CHAR_WHITETERR 5
  2149. #define   CHAR_HANDICAP 6
  2150. #define   CHAR_VERT 7
  2151. #define   ASC_NUMCHARS 8
  2152.  
  2153.  
  2154. WINDOW *boardwin, *serverwin, *iowin;
  2155. char xAxisChars[] = "ABCDEFGHJKLMNOPQRST";
  2156. int inverseFlag = 1;
  2157. int inverseBorder = 0;
  2158. int lastwin = 1;
  2159. int boardsize = -1;
  2160. char chars[] = ".#O?+-+ ";
  2161. int servecols = -1;
  2162. static int init = 0;
  2163. int endw = -1, endb = -1;
  2164. int reinit = 0;
  2165. int doedgemarkers = 0;
  2166. int dopiecemarkers = 1;
  2167.  
  2168. setedgemark(mark)
  2169. int mark;
  2170. {
  2171.    doedgemarkers = mark;
  2172. }
  2173.  
  2174. setpiecemark(mark)
  2175. int mark;
  2176. {
  2177.    dopiecemarkers = mark;
  2178. }
  2179.  
  2180. setinverse(inv)
  2181. int inv;
  2182. {
  2183.    inverseFlag = inv;
  2184. }
  2185.  
  2186. setinverseborder(inv)
  2187. int inv;
  2188. {
  2189.    inverseBorder = inv;
  2190. }
  2191.  
  2192. setborder(ch)
  2193. char ch;
  2194. {
  2195.    chars[CHAR_VERT] = ch;
  2196. }
  2197.  
  2198. setchars(s)
  2199. char *s;
  2200. {
  2201.    int i;
  2202.    for (i = 0; i <= min(CHAR_VERT, strlen(s) - 1); i++)
  2203.       chars[i] = s[i];
  2204. }
  2205.  
  2206.  
  2207. serverrefresh()
  2208. {
  2209.    if (lastwin)
  2210.       wrefresh(iowin);
  2211.    else
  2212.       wrefresh(serverwin);
  2213. }
  2214.  
  2215. boardrefresh()
  2216. {
  2217.    wrefresh(boardwin);
  2218. }
  2219.  
  2220. void initAscii()
  2221. {
  2222.    if (!init) {
  2223.       init = 1;
  2224.       initscr();
  2225.       noecho();
  2226.       crmode();
  2227.    }
  2228. }
  2229.  
  2230. suspend()
  2231. {
  2232.    move(23, 0);
  2233.    refresh();
  2234.    echo();
  2235.    nocrmode();
  2236. }
  2237.  
  2238.  
  2239.  
  2240. redraw()
  2241. {
  2242.    clearok(stdscr, TRUE);
  2243.    refresh();
  2244.    clearok(stdscr, FALSE);
  2245. }
  2246.  
  2247.  
  2248. unsuspend()
  2249. {
  2250.    noecho();
  2251.    crmode();
  2252.    redraw();
  2253. }
  2254.  
  2255.  
  2256. displaygamenumber(n)
  2257. int n;
  2258. {
  2259.    move(0, 0);
  2260.    if (n >= 0)
  2261.       printw("%3d", n);
  2262.    else if (n == -1)
  2263.       printw("-- ");
  2264.    else
  2265.       printw("sta");
  2266.    refresh();
  2267. }
  2268.  
  2269. boardtitle(bs, ws)
  2270. char *bs, *ws;
  2271. {
  2272.    int i;
  2273.    move(0, TITLEX);
  2274.    for (i = 0; i < 35; i++)
  2275.       addch(' ');
  2276.    move(1, TITLEX);
  2277.    for (i = 0; i < 35; i++)
  2278.       addch(' ');
  2279.    if (strlen(bs)) {
  2280.       move(0, TITLEX);
  2281.       printw("Black: %s", bs);
  2282.       endb = TITLEX + 8 + strlen(bs);
  2283.       move(1, TITLEX);
  2284.       printw("White: %s", ws);
  2285.       endw = TITLEX + 8 + strlen(ws);
  2286.    }
  2287.    refresh();
  2288. }
  2289.  
  2290. static void sbinverse()
  2291. {
  2292.    if (inverseBorder)
  2293.       wstandout(boardwin);
  2294. }
  2295.  
  2296. static void set_inverse()
  2297. {
  2298.    if (inverseFlag)
  2299.       wstandout(boardwin);
  2300. }
  2301.  
  2302. static void unset_inverse()
  2303. {
  2304.    wstandend(boardwin);
  2305. }
  2306.  
  2307.  
  2308. setcursor(x, y)
  2309. int x, y;
  2310. {
  2311.    wmove(boardwin, TOP + y, LEFT + 2 * x);
  2312.    wrefresh(boardwin);
  2313. }
  2314.  
  2315.  
  2316. void drawPiece(i, j, c)
  2317. int i, j;
  2318. char c;
  2319. {
  2320.    wmove(boardwin, TOP + j, LEFT + 2 * i);
  2321.    set_inverse();
  2322.    waddch(boardwin, c);
  2323.    unset_inverse();
  2324. }
  2325.  
  2326.  
  2327. void deleteBoardAscii()
  2328. {
  2329.    delwin(boardwin);
  2330.    delwin(serverwin);
  2331.    delwin(iowin);
  2332. }
  2333.  
  2334.  
  2335. void endAscii()
  2336. {
  2337.    init = 0;
  2338.    deleteBoardAscii();
  2339.    boardsize = -1;
  2340.    clear();
  2341.    refresh();
  2342.    echo();
  2343.    nocrmode();
  2344.    endwin();
  2345. }
  2346.  
  2347.  
  2348. char boardPiece(x, y, boardsize)
  2349. int x, y, boardsize;
  2350. {
  2351.    return
  2352.  
  2353.       (((boardsize == 19 && x == 9) || (boardsize >= 10 &&
  2354.                     (x == 3 || x == boardsize - 4))
  2355.     || (boardsize > 6 && boardsize < 10 &&
  2356.         (x == 2 || x == boardsize - 3))) &&
  2357.        ((boardsize == 19 && y == 9) ||
  2358.     (boardsize >= 10 && (y == 3 || y == boardsize - 4))
  2359.     || (boardsize > 6 && boardsize < 10 &&
  2360.         (y == 2 || y == boardsize - 3))))
  2361.       ? chars[(int) CHAR_HANDICAP] : chars[(int) CHAR_NOTHING];
  2362. }
  2363.  
  2364.  
  2365.  
  2366. drawOneStone(i, j, t)
  2367. int i, j;
  2368. piece t;
  2369. {
  2370.    if (t == 0)
  2371.       drawPiece(i, j, boardPiece(i, j, boardsize));
  2372.    else
  2373.       drawPiece(i, j, chars[t]);
  2374.    wrefresh(boardwin);
  2375. }
  2376.  
  2377. drawStone(i, j, t)
  2378. int i, j;
  2379. piece t;
  2380. {
  2381.    if (t == 0)
  2382.       drawPiece(i, j, boardPiece(i, j, boardsize));
  2383.    else
  2384.       drawPiece(i, j, chars[t]);
  2385. }
  2386.  
  2387.  
  2388. unmarkascii(i, j)
  2389. int i, j;
  2390. {
  2391.    if (!init)
  2392.       return;
  2393.    if (i >= 0 && i <= 19) {
  2394.       set_inverse();
  2395.       if (dopiecemarkers) {
  2396.      wmove(boardwin, TOP + j, LEFT + 2 * i - 1);
  2397.      waddch(boardwin, ' ');
  2398.      wmove(boardwin, TOP + j, LEFT + 2 * i + 1);
  2399.      waddch(boardwin, ' ');
  2400.       }
  2401.       if (doedgemarkers) {
  2402.      wmove(boardwin, TOP + j, LEFT - 1);
  2403.      waddch(boardwin, chars[CHAR_VERT]);
  2404.      wmove(boardwin, TOP + j, LEFT + boardsize * 2 - 1);
  2405.      waddch(boardwin, chars[CHAR_VERT]);
  2406.      unset_inverse();
  2407.      sbinverse();
  2408.      wmove(boardwin, TOP - 1, LEFT + i * 2);
  2409.      waddch(boardwin, xAxisChars[i]);
  2410.      wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  2411.      waddch(boardwin, xAxisChars[i]);
  2412.       }
  2413.       unset_inverse();
  2414.    }
  2415. }
  2416.  
  2417. unhighlight(i, j)
  2418. int i, j;
  2419. {
  2420.    int k;
  2421.    if (!init)
  2422.       return;
  2423.    move(HIGHLIGHT, 0);
  2424.    for (k = 1; k < 80 - servecols; k++)
  2425.       addch(' ');
  2426.    move(0, TITLEX - 2);
  2427.    printw("  ");
  2428.    move(1, TITLEX - 2);
  2429.    printw("  ");
  2430.    unmarkascii(i, j);
  2431. }
  2432.  
  2433. static char *who[] =
  2434. {"Black", "White"};
  2435.  
  2436. showhcap(hcap)
  2437. int hcap;
  2438. {
  2439.    if (!init)
  2440.       return;
  2441.    move(0, LEFT + 19 * 2 + 1);
  2442.    if (hcap)
  2443.       printw("%d", hcap);
  2444.    else
  2445.       addch(' ');
  2446.    refresh();
  2447. }
  2448.  
  2449. showkomi(komi)
  2450. float komi;
  2451. {
  2452.    if (!init)
  2453.       return;
  2454.    move(1, LEFT + 19 * 2 - 1);
  2455.    printw("%1.1f", komi);
  2456.    refresh();
  2457. }
  2458.  
  2459. highlight(i, j, num, t, btime, bbyo, wtime, wbyo)
  2460. int i, j;
  2461. piece t;
  2462. int btime, bbyo, wtime, wbyo;
  2463. {
  2464.    int k;
  2465.    if (btime != -1) {
  2466.       move(0, endb);
  2467.       if (btime < 0)
  2468.      btime = 0;
  2469.       if (wtime < 0)
  2470.      wtime = 0;
  2471.       printw("%d:%02d", btime / 60, btime % 60);
  2472.       if (bbyo != -1)
  2473.      printw(", %d", bbyo);
  2474.       addstr("   ");
  2475.       move(1, endw);
  2476.       printw("%d:%02d", wtime / 60, wtime % 60);
  2477.       if (wbyo != -1)
  2478.      printw(", %d", wbyo);
  2479.       addstr("   ");
  2480.    }
  2481.    if (t >= 0) {
  2482.       move(t == 1 ? 1 : 0, TITLEX - 2);
  2483.       printw("->");
  2484.    }
  2485.    move(HIGHLIGHT, 0);
  2486.    for (k = 1; k < 80 - servecols; k++)
  2487.       addch(' ');
  2488.    if (i == 99) {
  2489.       move(HIGHLIGHT, 0);
  2490.       printw("%s #%d Pass", who[t - 1], num);
  2491.    } else if (i < 100 && num) {
  2492.       move(HIGHLIGHT, 0);
  2493.       printw("%s #%d at %c%d", who[t - 1], num, i + 'A' +
  2494.          (i + 'A' >= 'I' ? 1 : 0), boardsize - j);
  2495.       set_inverse();
  2496.       if (dopiecemarkers) {
  2497.      wmove(boardwin, TOP + j, LEFT + 2 * i - 1);
  2498.      waddch(boardwin, '>');
  2499.      wmove(boardwin, TOP + j, LEFT + 2 * i + 1);
  2500.      waddch(boardwin, '<');
  2501.       }
  2502.       if (doedgemarkers) {
  2503.      wmove(boardwin, TOP + j, LEFT - 1);
  2504.      waddch(boardwin, '>');
  2505.      wmove(boardwin, TOP + j, LEFT + boardsize * 2 - 1);
  2506.      waddch(boardwin, '<');
  2507.      unset_inverse();
  2508.      sbinverse();
  2509.      wmove(boardwin, TOP - 1, LEFT + i * 2);
  2510.      waddch(boardwin, '!');
  2511.      wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  2512.      waddch(boardwin, '!');
  2513.       }
  2514.       unset_inverse();
  2515.    }
  2516. }
  2517.  
  2518.  
  2519.  
  2520. drawpris(pris)
  2521. int *pris;
  2522. {
  2523.    move(23, 22);
  2524.    printw("Captured %c: %d  %c: %d  ", chars[CHAR_BLACK], *pris,
  2525.       chars[CHAR_WHITE], pris[1]);
  2526.    refresh();
  2527. }
  2528.  
  2529.  
  2530.  
  2531. void initBoardAscii(size)
  2532. int size;
  2533. {
  2534.    int i, j;
  2535.    if (!reinit) {
  2536.       if (size == boardsize) {
  2537.      for (i = boardsize; i--;)
  2538.         for (j = boardsize; j--;)
  2539.            drawStone(i, j, 0);
  2540.      return;
  2541.       }
  2542.       if (boardsize != -1)
  2543.      deleteBoardAscii();
  2544.       boardsize = size;
  2545.       clear();
  2546.       boardwin = subwin(stdscr, boardsize + 4, boardsize * 2 - 1 + 6 + 2, 1, 0);
  2547.       servecols = COLS - 19 * 2 - 6 - 2;
  2548.       serverwin = subwin(stdscr, 22, servecols, 0, 19 * 2 - 1 + 6 + 2);
  2549.  
  2550.       iowin = subwin(stdscr, 2, servecols, 22, 19 * 2 - 1 + 6 + 2);
  2551.    }
  2552.    if (inverseFlag || reinit) {
  2553.       set_inverse();
  2554.       for (i = LEFT + 1; i < LEFT + boardsize * 2 - 2; i += 2)
  2555.      for (j = TOP; j < TOP + boardsize; j++)
  2556.         mvwaddch(boardwin, j, i, ' ');
  2557.       unset_inverse();
  2558.    }
  2559.    for (i = boardsize; i--;) {
  2560.       /* left */
  2561.       wmove(boardwin, TOP + i, LEFT - 3);
  2562.       sbinverse();
  2563.       wprintw(boardwin, "%2d", boardsize - i);
  2564.       unset_inverse();
  2565.       set_inverse();
  2566.       waddch(boardwin, chars[(int) CHAR_VERT]);
  2567.  
  2568.       /* right */
  2569.       wmove(boardwin, TOP + i, LEFT + boardsize * 2 - 1);
  2570.       waddch(boardwin, chars[(int) CHAR_VERT]);
  2571.       unset_inverse();
  2572.       sbinverse();
  2573.       wprintw(boardwin, "%2d", boardsize - i);
  2574.       unset_inverse();
  2575.       waddch(boardwin, chars[(int) CHAR_VERT]);
  2576.  
  2577.       /* top */
  2578.       wmove(boardwin, TOP - 1, LEFT + i * 2);
  2579.       sbinverse();
  2580.       waddch(boardwin, xAxisChars[i]);
  2581.       waddch(boardwin, ' ');
  2582.       unset_inverse();
  2583.       wmove(boardwin, TOP - 1, LEFT + i * 2 - 1);
  2584.       set_inverse();
  2585.  
  2586.       /* bottom */
  2587.       wmove(boardwin, TOP + boardsize, LEFT + i * 2 - 1);
  2588.       unset_inverse();
  2589.       wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  2590.       sbinverse();
  2591.       waddch(boardwin, xAxisChars[i]);
  2592.       waddch(boardwin, ' ');
  2593.       unset_inverse();
  2594.       for (j = boardsize; j--;)
  2595.      drawStone(i, j, 0);
  2596.    }
  2597.  
  2598.    sbinverse();
  2599.    wmove(boardwin, TOP - 1, LEFT - 3);
  2600.    waddstr(boardwin, "   ");
  2601.    wmove(boardwin, TOP + boardsize, LEFT - 3);
  2602.    waddstr(boardwin, "   ");
  2603.    wmove(boardwin, TOP - 1, LEFT + 2 * boardsize);
  2604.    waddstr(boardwin, "  ");
  2605.    wmove(boardwin, TOP + boardsize, LEFT + 2 * boardsize);
  2606.    waddstr(boardwin, "  ");
  2607.    unset_inverse();
  2608.  
  2609.    wmove(boardwin, size / 2, size / 2);
  2610. }
  2611.  
  2612. reinitboardascii()
  2613. {
  2614.    reinit = 1;
  2615.    initBoardAscii(boardsize);
  2616.    reinit = 0;
  2617. }
  2618.  
  2619.  
  2620. clearserver()
  2621. {
  2622.    wclear(serverwin);
  2623.    wrefresh(serverwin);
  2624. }
  2625.  
  2626.  
  2627. addcharline(pos, ch)
  2628. int pos;
  2629. char ch;
  2630. {
  2631.    wmove(iowin, 1, pos);
  2632.    waddch(iowin, ch);
  2633.    wrefresh(iowin);
  2634.    lastwin = 1;
  2635. }
  2636.  
  2637.  
  2638. deletechar(pos)
  2639. int pos;
  2640. {
  2641.    wmove(iowin, 1, pos);
  2642.    waddch(iowin, ' ');
  2643.    wmove(iowin, 1, pos);
  2644.    wrefresh(iowin);
  2645.    lastwin = 1;
  2646. }
  2647.  
  2648.  
  2649.  
  2650. int linesize()
  2651. {
  2652.    return servecols - 2;
  2653. }
  2654.  
  2655. clrline()
  2656. {
  2657.    wmove(iowin, 1, 0);
  2658.    wclrtoeol(iowin);
  2659.    wrefresh(iowin);
  2660. }
  2661.  
  2662.  
  2663. addchar(ch)
  2664. char ch;
  2665. {
  2666.    int x, y, maxx, maxy;
  2667.    if (ch == '\r')
  2668.       return;
  2669.    waddch(serverwin, ch);
  2670.    maxy = serverwin->_maxy - 1;    /* 20 */
  2671.    maxx = serverwin->_maxx - 1;    /* servecols - 1; */
  2672.    getyx(serverwin, y, x);
  2673.    if ((x == maxx - 1 && y == maxy) || (ch == '\n' && y == maxy) ||
  2674.        y > maxy) {
  2675.       wmove(serverwin, 0, 0);
  2676.       wclrtoeol(serverwin);
  2677.    } else if (x == 0 && y <= maxy) {
  2678.       wclrtoeol(serverwin);
  2679.       wmove(serverwin, y + 1, 0);
  2680.       wclrtoeol(serverwin);
  2681.       wmove(serverwin, y, x);
  2682.    }
  2683.    wrefresh(serverwin);
  2684.    lastwin = 0;
  2685. }
  2686.  
  2687. showprefix(s)
  2688. char *s;
  2689. {
  2690.    wmove(iowin, 0, 0);
  2691.    wclrtoeol(iowin);
  2692.    if (strlen(s))
  2693.       wprintw(iowin, "Prefix: '%s'", s);
  2694.    wrefresh(iowin);
  2695. }
  2696.  
  2697.  
  2698. /* addstring(s) char *s; { char *p; for (p = s; *p; p++) addchar(*p); } */
  2699.  
  2700. void addstring(s)        /* add a string of chars to server win     */
  2701. char *s;
  2702. {
  2703.    char *p, *q;
  2704.    char word[64];
  2705.    int count;
  2706.    /* parse a word. if it doesn't wrap, addchar it */
  2707.    /* if it does then addchar a \n and then word */
  2708.    count = 0;
  2709.    p = s;
  2710.    while (*p) {
  2711.       q = word;
  2712.       while (*p != ' ' && *p != '\n' && *p != '\0') {
  2713.      *q = *p;
  2714.      q++;
  2715.      p++;
  2716.       }
  2717.  
  2718.       *q = *p;
  2719.       q++;
  2720.       if (*p)
  2721.      p++;
  2722.       *q = '\0';
  2723.       if (count + strlen(word) > 32) {
  2724.      addchar('\n');
  2725.      count = 0;
  2726.       }
  2727.       count += strlen(word);
  2728.       count %= 33;
  2729.       if (p[-1] == '\n')
  2730.      count = 0;
  2731.       for (q = word; *q; q++)
  2732.      addchar(*q);
  2733.  
  2734.    }
  2735. }
  2736.  
  2737.  
  2738. bigmess(lines, intext)
  2739. int lines;
  2740. char *intext;
  2741. {
  2742.    WINDOW *savescr;
  2743.    char ch;
  2744.    int i, count;
  2745.    int rest;
  2746.    char *mynl, *localcopy, *text;
  2747.  
  2748.    text = localcopy = (char *) malloc(strlen(intext) + 1);
  2749.    strcpy(text, intext);
  2750.    mynl = "";
  2751.    if (lines > 22) {
  2752.       rest = lines;
  2753.       lines = 22;
  2754.    } else
  2755.       rest = 0;
  2756.    savescr = newwin(24, 80, 0, 0);
  2757.    overwrite(stdscr, savescr);
  2758.    do {
  2759.       if (rest > 0) {
  2760.      for (mynl = text, count = 22; count && *mynl; mynl++)
  2761.         if (*mynl == '\n')
  2762.            count--;
  2763.      *(mynl - 1) = 0;
  2764.      rest -= 22;
  2765.       }
  2766.       for (i = (24 - lines) / 2 - 1; i < (24 - lines) / 2 + lines + 1; i++) {
  2767.      move(i, 0);
  2768.      clrtoeol();
  2769.       }
  2770.       move((24 - lines) / 2, 0);
  2771.       addstr(text);
  2772.       refresh();
  2773.       while (read(0, &ch, 1) != 1);
  2774.       text = mynl;
  2775.    } while (rest > 0);
  2776.    overwrite(savescr, stdscr);
  2777.    refresh();
  2778.    delwin(savescr);
  2779.    free(localcopy);
  2780. }
  2781. SHAR_EOF
  2782. fi
  2783. if test -f 'board.c'
  2784. then
  2785.     echo shar: "will not over-write existing file 'board.c'"
  2786. else
  2787. cat << \SHAR_EOF > 'board.c'
  2788. #include "igc.h"
  2789.  
  2790. typedef char boardtype[19][19];
  2791. int prisoners[2];
  2792. int movenum, maxmove;
  2793.  
  2794. typedef struct {
  2795.    int x, y;
  2796.    char col;
  2797. }  movelist[500];
  2798.  
  2799. movelist moves;
  2800.  
  2801. boardtype board;
  2802.  
  2803. #define boolean char
  2804. #define false 0
  2805. #define true 1
  2806.  
  2807. static int boardsize = -1;
  2808.  
  2809. int lasti = -1, lastj = -1;
  2810.  
  2811.  
  2812. clearboard(b, pris)
  2813. boardtype b;
  2814. int *pris;
  2815. {
  2816.    int i, j;
  2817.    pris[0] = pris[1] = 0;
  2818.    for (i = 0; i < boardsize; i++)
  2819.       for (j = 0; j < boardsize; j++)
  2820.      b[i][j] = EMPTY;
  2821. }
  2822.  
  2823.  
  2824. initboard(size)
  2825. int size;
  2826. {
  2827.    clearboard(board, prisoners);
  2828.    unhighlight(lasti, lastj);
  2829.    showhcap(0);
  2830.    initAscii();
  2831.    initBoardAscii(size);
  2832.    boardsize = size;
  2833.    maxmove = movenum = 0;
  2834. }
  2835.  
  2836.  
  2837. reinitboard(size)
  2838. int size;
  2839. {
  2840.    unhighlight(lasti, lastj);
  2841.    showhcap(0);
  2842.    clearboard(board, prisoners);
  2843.    initAscii();
  2844.    reinitboardascii();
  2845.    boardsize = size;
  2846. }
  2847.  
  2848. boolean inRange(i, j)
  2849. {
  2850.    return i >= 0 && i < boardsize && j >= 0 && j < boardsize;
  2851. }
  2852.  
  2853. boolean alive0(b, m, i, j, t)
  2854. boardtype b;
  2855. boardtype m;
  2856. int i, j;
  2857. piece t;
  2858. {
  2859.    piece pt;
  2860.  
  2861.    pt = b[i][j];
  2862.    if ((pt != EMPTY && pt != t) || m[i][j] != EMPTY)
  2863.       return 0;
  2864.    m[i][j] = (pt == t) ? (piece) 1 : (piece) 2;
  2865.    if (pt == EMPTY)
  2866.       return 1;
  2867.    return
  2868.       (j < boardsize - 1 && alive0(b, m, i, j + 1, t)) ||
  2869.       (i < boardsize - 1 && alive0(b, m, i + 1, j, t)) ||
  2870.       (i && alive0(b, m, i - 1, j, t)) ||
  2871.       (j && alive0(b, m, i, j - 1, t));
  2872. }
  2873.  
  2874. boolean alive(b, i, j)        /* Does group at i,j have liberties? */
  2875. boardtype b;
  2876. int i, j;
  2877. {
  2878.    boardtype m;
  2879.    int p[2];
  2880.  
  2881.    clearboard(m, p);
  2882.    return alive0(b, m, i, j, b[i][j]);
  2883. }
  2884.  
  2885. int removed;
  2886. int dontdraw = 0;
  2887.  
  2888. void removeStones0(b, pris, i, j, t)
  2889. boardtype b;
  2890. int *pris;
  2891. int i, j;
  2892. piece t;
  2893. {
  2894.    if (b[i][j] != t)
  2895.       return;
  2896.    b[i][j] = EMPTY;
  2897.    if (!dontdraw)
  2898.       drawStone(i, j, 0);
  2899.    removed = 1;
  2900.    pris[t - 1]++;
  2901.    if (j < boardsize - 1)
  2902.       removeStones0(b, pris, i, j + 1, t);
  2903.    if (i < boardsize - 1)
  2904.       removeStones0(b, pris, i + 1, j, t);
  2905.    if (i)
  2906.       removeStones0(b, pris, i - 1, j, t);
  2907.    if (j)
  2908.       removeStones0(b, pris, i, j - 1, t);
  2909. }
  2910.  
  2911.  
  2912.  
  2913. void removeStones(b, pris, i, j)
  2914. boardtype b;
  2915. int *pris;
  2916. int i, j;
  2917. {
  2918.    removed = 0;
  2919.    removeStones0(b, pris, i, j, b[i][j]);
  2920.    /* if (removed) boardrefresh(); */
  2921.  
  2922. }
  2923.  
  2924.  
  2925. void removeGroup(i, j)
  2926. int i, j;
  2927. {
  2928.    removeStones(board, prisoners, i, j);
  2929. }
  2930.  
  2931. boolean tryKill(b, pris, i, j, t)
  2932. boardtype b;
  2933. int *pris;
  2934. int i, j;
  2935. piece t;
  2936. {
  2937.    piece w;
  2938.    if (!inRange(i, j))
  2939.       return false;
  2940.    w = b[i][j];
  2941.    if (w != EMPTY && w != t && !alive(b, i, j)) {
  2942.       removeStones(b, pris, i, j);
  2943.       return true;
  2944.    }
  2945.    return false;
  2946. }
  2947.  
  2948. void placeStone(b, pris, i, j, t)
  2949. boardtype b;
  2950. int *pris;
  2951. int i, j;
  2952. piece t;
  2953. {
  2954.    if (inRange(i, j)) {
  2955.       b[i][j] = t;
  2956.       if (j)
  2957.      tryKill(b, pris, i, j - 1, t);
  2958.       if (j < boardsize - 1)
  2959.      tryKill(b, pris, i, j + 1, t);
  2960.       if (i)
  2961.      tryKill(b, pris, i - 1, j, t);
  2962.       if (i < boardsize - 1)
  2963.      tryKill(b, pris, i + 1, j, t);
  2964.    }
  2965. }
  2966.  
  2967.  
  2968.  
  2969.  
  2970. static highlighting = 1;
  2971.  
  2972. makemove(i, j, num, t, btime, bbyo, wtime, wbyo)
  2973. int i, j;
  2974. piece t;
  2975. int btime, bbyo, wtime, wbyo;
  2976. {
  2977.    if (movenum != maxmove) {
  2978.       construct(maxmove);
  2979.    }
  2980.    if (highlighting)
  2981.       unhighlight(lasti, lastj);
  2982.    if (num == 1 && i <= 19)
  2983.       showhcap(0);
  2984.    if (i > 100) {
  2985.       sethandicap(board, i - 100);
  2986.       showhcap(i - 100);
  2987.       moves[num].x = moves[num].y = i;
  2988.       moves[num].col = t;
  2989.       maxmove = movenum = num;
  2990.       if (highlighting)
  2991.      highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  2992.       return;
  2993.    }
  2994.    if (i == 99) {
  2995.       moves[num].x = moves[num].y = 99;
  2996.       moves[num].col = t;
  2997.       maxmove = movenum = num;
  2998.       if (highlighting) {
  2999.      highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  3000.      drawpris(prisoners);
  3001.       }
  3002.       return;
  3003.    }
  3004.    placeStone(board, prisoners, i, j, t);
  3005.    if (highlighting)
  3006.       highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  3007.    if (highlighting)
  3008.       drawpris(prisoners);
  3009.    if (highlighting)
  3010.       drawOneStone(i, j, t);
  3011.    else
  3012.       drawStone(i, j, t);
  3013.    lasti = i;
  3014.    lastj = j;
  3015.    moves[num].x = i;
  3016.    moves[num].y = j;
  3017.    moves[num].col = t;
  3018.    maxmove = movenum = num;
  3019. }
  3020.  
  3021.  
  3022. unmark()
  3023. {
  3024.    unmarkascii(lasti, lastj);
  3025. }
  3026.  
  3027.  
  3028. construct(mov)
  3029. int mov;
  3030. {
  3031.    int i, j;
  3032.    boardtype myboard;
  3033.    int mypris[2];
  3034.  
  3035.    if (mov > maxmove)
  3036.       mov = maxmove;
  3037.    if (mov < 1)
  3038.       mov = 1;
  3039.    clearboard(myboard, mypris);
  3040.    unhighlight(lasti, lastj);
  3041.    dontdraw = 1;
  3042.    for (i = 1; i <= mov; i++) {
  3043.       if (moves[i].x > 100)
  3044.      sethandicap(myboard, moves[i].x - 100);
  3045.       else if (moves[i].x != 99) {
  3046.      placeStone(myboard, mypris, moves[i].x, moves[i].y, moves[i].col);
  3047.      myboard[moves[i].x][moves[i].y] = moves[i].col;
  3048.       }
  3049.    }
  3050.    dontdraw = 0;
  3051.    for (i = 0; i < boardsize; i++)
  3052.       for (j = 0; j < boardsize; j++)
  3053.      if (board[i][j] != myboard[i][j]) {
  3054.         drawStone(i, j, myboard[i][j]);
  3055.         board[i][j] = myboard[i][j];
  3056.      }
  3057.    prisoners[0] = mypris[0];
  3058.    prisoners[1] = mypris[1];
  3059.    highlight(moves[mov].x, moves[mov].y, mov, moves[mov].col,
  3060.          -1, -1, -1, -1);
  3061.    lasti = moves[mov].x;
  3062.    lastj = moves[mov].y;
  3063.    drawpris(prisoners);
  3064.    movenum = mov;
  3065. }
  3066.  
  3067.  
  3068. int savemaxmove = 0, didsave = 0;
  3069.  
  3070.  
  3071. restoremaxmoves()
  3072. {
  3073.    didsave = 0;
  3074.    maxmove = savemaxmove;
  3075. }
  3076.  
  3077. savemaxmoves()
  3078. {
  3079.    if (!didsave) {
  3080.       didsave = 1;
  3081.       savemaxmove = maxmove;
  3082.    }
  3083. }
  3084.  
  3085.  
  3086. showboard(b)
  3087. boardtype b;
  3088. {
  3089.    int i, j;
  3090.    for (i = 0; i < boardsize; i++)
  3091.       for (j = 0; j < boardsize; j++)
  3092.      if (board[i][j] != b[i][j]) {
  3093.         drawStone(i, j, b[i][j]);
  3094.         board[i][j] = b[i][j];
  3095.      }
  3096.    boardrefresh();
  3097. }
  3098.  
  3099.  
  3100. undo()
  3101. {
  3102.    int i, j;
  3103.  
  3104.    maxmove--;
  3105.    if (maxmove)
  3106.       construct(maxmove);
  3107.    else {
  3108.       movenum = 0;
  3109.       unhighlight(lasti, lastj);
  3110.       for (i = 0; i < boardsize; i++)
  3111.      for (j = 0; j < boardsize; j++)
  3112.         if (board[i][j] != EMPTY) {
  3113.            drawStone(i, j, EMPTY);
  3114.            board[i][j] = EMPTY;
  3115.         }
  3116.    }
  3117. }
  3118.  
  3119.  
  3120. int forward(num)
  3121. int num;
  3122. {
  3123.    if (!maxmove)
  3124.       return 1;
  3125.    if (movenum < maxmove)
  3126.       construct(movenum + num);    /* construct() does bounds checking */
  3127.    return 0;
  3128. }
  3129.  
  3130.  
  3131. int backward(num)
  3132. int num;
  3133. {
  3134.    if (!maxmove)
  3135.       return 1;
  3136.    if (movenum > 1)
  3137.       construct(movenum - num);    /* construct() does bounds checking */
  3138.    return 0;
  3139. }
  3140.  
  3141.  
  3142. int beginninggame()
  3143. {
  3144.    if (!maxmove)
  3145.       return 1;
  3146.    construct(1);
  3147.    return 0;
  3148. }
  3149.  
  3150. int endgame()
  3151. {
  3152.    if (!maxmove)
  3153.       return 1;
  3154.    construct(maxmove);
  3155.    return 0;
  3156. }
  3157.  
  3158.  
  3159. sethighlight(h)
  3160. int h;
  3161. {
  3162.    highlighting = h;
  3163. }
  3164.  
  3165. #define TOP 0
  3166. #define MID 1
  3167. #define BOT 2
  3168. static int verts[3][26] =
  3169. {
  3170.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3171.     2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 4},
  3172.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3173.     4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 9, 0, 10, 0, 0, 0, 12},
  3174.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3175.     6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 17, 0, 0, 0, 20},
  3176. };
  3177.  
  3178.  
  3179.  
  3180. sethandicap(board, hand)
  3181. boardtype board;
  3182. int hand;
  3183. {
  3184.    /* This is also used to set the handicap.  The 'handi' is the number of
  3185.     * things to set of piece 'p'. */
  3186.  
  3187.    int top, mid, bot;
  3188.    piece t;
  3189.  
  3190.    top = verts[TOP][boardsize];
  3191.    mid = verts[MID][boardsize];
  3192.    bot = verts[BOT][boardsize];
  3193.  
  3194.    /* All of these drop through, '5' checks for odd points. */
  3195.    t = 1;
  3196.    switch (hand) {
  3197.       case 9:            /* taken care of by handi == 5 */
  3198.       case 8:
  3199.      drawStone(mid, top, t);
  3200.      board[mid][top] = t;
  3201.      drawStone(mid, bot, t);
  3202.      board[mid][bot] = t;
  3203.       case 7:            /* taken care of by handi == 5 */
  3204.       case 6:
  3205.      drawStone(bot, mid, t);
  3206.      board[bot][mid] = t;
  3207.      drawStone(top, mid, t);
  3208.      board[top][mid] = t;
  3209.       case 5:
  3210.      if (hand & 0x1) {    /* odd points, test because of drop through */
  3211.         drawStone(mid, mid, t);
  3212.         board[mid][mid] = t;
  3213.      }
  3214.       case 4:
  3215.      drawStone(bot, bot, t);
  3216.      board[bot][bot] = t;
  3217.       case 3:
  3218.      drawStone(top, top, t);
  3219.      board[top][top] = t;
  3220.       case 2:
  3221.      drawStone(bot, top, t);
  3222.      board[bot][top] = t;
  3223.      drawStone(top, bot, t);
  3224.      board[top][bot] = t;
  3225.      break;
  3226.       default:
  3227.      break;
  3228.    }
  3229. }
  3230. SHAR_EOF
  3231. fi
  3232. if test -f 'numbers.h'
  3233. then
  3234.     echo shar: "will not over-write existing file 'numbers.h'"
  3235. else
  3236. cat << \SHAR_EOF > 'numbers.h'
  3237.  
  3238.  
  3239. typedef enum {
  3240.    UNKNOWN = 0,
  3241.    BEEP = 2,            /* \7 telnet          */
  3242.    BOARD = 3,            /* Board being drawn      */
  3243.    DOWN = 4,            /* The server is going down */
  3244.    ERROR = 5,            /* An error reported     */
  3245.    FIL = 6,            /* File being sent     */
  3246.    GAMES = 7,            /* Games listing     */
  3247.    HELP = 8,            /* Help file         */
  3248.    INFO = 9,            /* Generic info         */
  3249.    LAST = 10,            /* Last command         */
  3250.    KIBITZ = 11,            /* Kibitz strings     */
  3251.    LOAD = 12,            /* Loading a game     */
  3252.    LOOK = 13,            /* Look          */
  3253.    MESSAGE = 14,        /* Message lising     */
  3254.    MOVE = 15,            /* Move #:(B) A1     */
  3255.    OBSERVE = 16,        /* Observe report     */
  3256.    PROMPT = 1,            /* A Prompt (never)     */
  3257.    REFRESH = 17,        /* Refresh of a board     */
  3258.    SAVED = 18,            /* Stored command     */
  3259.    SAY = 19,            /* Say string         */
  3260.    SCORE = 20,            /* Score report         */
  3261.    SHOUT = 21,            /* Shout string         */
  3262.    STATUS = 22,            /* Current Game status     */
  3263.    STORED = 23,            /* Stored games         */
  3264.    TELL = 24,            /* Tell string         */
  3265.    THIST = 25,            /* Thist report         */
  3266.    TIM = 26,            /* times command     */
  3267.    WHO = 27,            /* who command         */
  3268.    UNDO = 28,            /* Undo report         */
  3269.    TRANSLATE = 30
  3270. }  MessageType;
  3271.  
  3272.  
  3273. #define    S_BLACK  '0'
  3274. #define    S_WHITE  '1'
  3275. #define    S_EMPTY  '2'
  3276. #define    S_DAME   '3'
  3277. #define    S_WTERR  '4'
  3278. #define    S_BTERR  '5'
  3279. #define    S_HOSHI  '6'
  3280.  
  3281.  
  3282. #define    LOGON  0
  3283. #define    PASSWORD  1
  3284. #define    PASSWD_NEW  2
  3285. #define    PASSWD_CONFIRM  3
  3286. #define    REGISTER  4
  3287. #define    WAITING  5
  3288. #define    PLAYING  6
  3289. #define    SCORING  7
  3290. #define    OBSERVING  8
  3291.  
  3292.  
  3293. SHAR_EOF
  3294. fi
  3295. if test -f 'igc.h'
  3296. then
  3297.     echo shar: "will not over-write existing file 'igc.h'"
  3298. else
  3299. cat << \SHAR_EOF > 'igc.h'
  3300. #define MAXGAMES 20
  3301. #define MAXWHO 300
  3302. #define MAXNAME 11
  3303. #define MAXRANK 6
  3304. #define piece char
  3305.  
  3306. #ifdef BCOPY
  3307. #define bcopy(a,b,c) memcpy(b,a,c)
  3308. #endif
  3309.  
  3310. typedef struct {
  3311.    int id;
  3312.  
  3313.    int prompttype;        /* if return is prompt */
  3314.  
  3315.    int x, y;            /* used to report removed stones for scoring */
  3316.  
  3317.  
  3318.    struct {            /* if return is play */
  3319.       int x, y;
  3320.       int movenum;
  3321.       int color;
  3322.    }  moves[400];
  3323.  
  3324.    int movecount;
  3325.    int gamenum;
  3326.    int bcap, btime, bbyo;
  3327.    int wcap, wtime, wbyo;
  3328.  
  3329.    char text[10000];        /* text of message */
  3330.    int lines;            /* number of lines in text */
  3331.  
  3332.    int gamecount;        /* for data from the games command */
  3333.    struct {
  3334.       int gnum;
  3335.       char white[MAXNAME], wrank[MAXRANK], black[MAXNAME], brank[MAXRANK];
  3336.       int mnum, bsize, hcap;
  3337.       float komi;
  3338.    }  gamelist[MAXGAMES];
  3339.  
  3340.    int boardsize, boardline;
  3341.    float wscore, bscore;
  3342.    piece board[19][19];
  3343.    int wnext;            /* white next?  Already have info for black. */
  3344.    char white[MAXNAME], wrank[MAXRANK], black[MAXNAME], brank[MAXRANK];
  3345.    int hcap;
  3346.  
  3347.    int beep;
  3348.  
  3349.    char kibitzer[40];
  3350.    char kibitz[300];
  3351.  
  3352.    char whocount;
  3353.    char *who[MAXWHO];
  3354.    char whodata[MAXWHO][40];
  3355.    char wholast[80];
  3356.    char whofirst[80];
  3357.  
  3358.    float mykomi;
  3359.  
  3360. }  message;
  3361.  
  3362.  
  3363.  
  3364. #define ONSERVER -1
  3365. #define MATCH -2
  3366. #define QUITMESG -3
  3367. #define REMOVE -4
  3368. #define SCOREUNDO -5
  3369. #define TIMEREP -6
  3370. #define TOOMANY -7
  3371. #define CHKOMI -8
  3372.  
  3373. #define BLACK 1
  3374. #define WHITE 2
  3375. #define EMPTY 0
  3376. #define DAME 3
  3377. #define BTERR 4
  3378. #define WTERR 5
  3379.  
  3380. #define KEY -33
  3381. SHAR_EOF
  3382. fi
  3383. if test -f 'Makefile'
  3384. then
  3385.     echo shar: "will not over-write existing file 'Makefile'"
  3386. else
  3387. cat << \SHAR_EOF > 'Makefile'
  3388. CC = cc 
  3389.  
  3390. # if you get strstr undefined, add -DSTRSTR to the DEFINES line below
  3391. # if you get bcopy undefined, add -DBCOPY 
  3392. # if you get strtol undefined, add -DSTRTOL
  3393.  
  3394. # if you change something in the Makefile, you may need to 
  3395. # type rm *.o before trying to recompile.
  3396.  
  3397. # The -DDEBUG below causes igc to create dump?.igc files which 
  3398. # contain logs of each IGS session.  Remove the -DDEBUG
  3399. # to suppress creation of the dump files.  I may request 
  3400. # the log files from you if you report bugs.
  3401.  
  3402. DEFINES = -DDEBUG 
  3403.  
  3404. # You may want to change -g (include debug information) into
  3405. # -O for optimize.  If you do this, also run strip on the 
  3406. # igc file:  'strip igc'.  This will make the executable
  3407. # even smaller.
  3408.  
  3409. CFLAGS = -g  $(DEFINES) 
  3410.  
  3411. LIBS =     -lcurses -ltermlib
  3412.  
  3413. # link line for PTX.  System V systems need something like this:
  3414. #LIBS = -lcurses -ltermlib -lsocket -linet -lnsl 
  3415.  
  3416. # Under Irix running Yellow Pages, add -lsun to the link line
  3417.  
  3418. # Under RS/6000 AIX 3.1, remove the -ltermlib 
  3419.  
  3420. PROGRAM = igc
  3421.  
  3422. MAN = igc.doc
  3423.  
  3424. OBJ = socket.o igc.o parse.o ascii.o board.o
  3425.  
  3426. SRC = socket.c igc.c parse.c ascii.c board.c
  3427.  
  3428. HDRS =    numbers.h igc.h
  3429.  
  3430. FILES = README $(SRC) $(HDRS) Makefile igc.6
  3431.  
  3432. all: $(PROGRAM) $(MAN)
  3433.  
  3434. $(PROGRAM): $(OBJ)
  3435.     @echo Loading...
  3436.     @$(CC) $(OBJ) $(LIBS) -o $(PROGRAM)
  3437.  
  3438. $(MAN): igc.6
  3439.     nroff -man igc.6 > $(MAN)
  3440.  
  3441. $(OBJ): $(HDRS)
  3442.  
  3443. shar: 
  3444.     @shar $(FILES) > $(PROGRAM).shar
  3445.  
  3446. shar2: 
  3447.     @shar -m 200000 -f $(PROGRAM) $(FILES) 
  3448.  
  3449. lint:
  3450.     lint $(SRC) -lcurses > lintout
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459. SHAR_EOF
  3460. fi
  3461. if test -f 'igc.6'
  3462. then
  3463.     echo shar: "will not over-write existing file 'igc.6'"
  3464. else
  3465. cat << \SHAR_EOF > 'igc.6'
  3466. .TH IGC 6   "9 September 1992"
  3467. .SH NAME
  3468. igc - ascii client to Internet Go Server
  3469. .SH SYNOPSIS
  3470. .B igc
  3471. [\-s] [host [port]]
  3472. .SH DESCRIPTION
  3473. Go is an ancient asian strategy game based on the capture of
  3474. territory.
  3475. Players alternate, placing stones on the board and trying to surround
  3476. as many empty intersections as possible.  The 
  3477. .B Internet Go Server
  3478. allows players to meet and play interactive games.  
  3479. .B Igc
  3480. provides a more convenient interface for connections to the 
  3481. .B Internet Go Server.
  3482. .SH COMMAND LINE OPTIONS
  3483. .TP 8
  3484. .B \-s
  3485. Supresses autologin.
  3486. .LP
  3487. .TP 8
  3488. .B [host [port]]
  3489. Connects to specified host and port number.  The host can be specified
  3490. as a fully qualified hostname, or as an abbreviation.  If the
  3491. abbreviation is used, then the port number cannot be included.  
  3492. The shorthand names supported by default are:
  3493. .in +2m
  3494. .ta
  3495. .ta 7m +\w'mmmmm\ \ 'u +\w'icsib18.icsi.berkeley.edu\ \ 'u +
  3496. .nf
  3497.     name    host address    port
  3498. site0    icsi    icsib18.icsi.berkeley.edu    6969
  3499. site1    cnam    cnam.cnam.fr    6969
  3500. .nf
  3501. .in -2m
  3502. If no host is specified, then site0 is used.
  3503. To connect to the French site, for example, 
  3504. use 'igc cnam'.  
  3505. (See the customization section for more information.)
  3506. .SH OPERATION
  3507. When 
  3508. .B igc 
  3509. is run, it opens a connection to the go server.  Unlike a straight
  3510. telnet connection, 
  3511. .B igc
  3512. does not print the '#>' prompt, and your normal suspend key (usually
  3513. ^Z) will suspend the client.  If you use telnet after using 
  3514. .B igc
  3515. the prompts from the server will be different because the server is in
  3516. client mode.  Log in with username and password at the numeric
  3517. prompts and then type 'toggle client' to get the normal prompts.
  3518. .LP
  3519. Initially, 
  3520. .B igc
  3521. acts as a direct connection to the server.  When a game is displayed,
  3522. the screen will be split into two windows:  one for the board on the
  3523. left, and one
  3524. for text interaction with the server on the right.  The 
  3525. ESC key will switch between
  3526. the two windows, and the ^L key will redraw the display (from either
  3527. window).  
  3528. .LP
  3529. When the server sends long messages such as the output from 
  3530. the 'games' command, the 'who' command, or the 'help' commmand, it
  3531. prints the message on top of the board.  Press any key to restore the
  3532. board.  If the message is longer than 22 lines, then the message will
  3533. be displayed in chunks.  
  3534. .LP
  3535. The names of the players appear above the board, followed by their
  3536. ranks, and the time remaining.  An arrow indicates whose turn
  3537. it is.  You can view only one game
  3538. at a time (either by observing, or by playing).  The number of 
  3539. that game is displayed to the left of the Black's name.
  3540. This number should be '--' if
  3541. you are not playing or observing a game.  To the right of Black's
  3542. name, above the right corner of the board (in 19x19 games),
  3543. is the number of handicap
  3544. stones.  This region is blank if the game is even. 
  3545. To the right of white's name is the komi for the game.  
  3546. Below the board, a line shows the number and coordinates of the last
  3547. move, and the captured stones are displayed.  The display shows the
  3548. number of black stones which were captured, followed by the
  3549. number of white stones captured.  
  3550. .LP
  3551. All of the commands which are active from the board window are single
  3552. keystroke commands.  The cursor can be moved around the board using
  3553. either the number keys (12346789), the emacs keys (^P ^N ^B ^F) or the
  3554. rogue keys (hjklyubn).  The board keeps track of all moves received so
  3555. that you can view the history of the game.  Note that the 
  3556. server's 'look' and 'status' commands do not generate a move history. 
  3557. When these commands are used, or when a game is scored, a snapshot of
  3558. the board is obtained from the server and temporarily placed on top of
  3559. the board.  The receipt of a move, or any attempt to move through the
  3560. game record, will restore the previous display.  When the status
  3561. display is active, the game number area in the upper right corner of
  3562. the screen reads "sta".  The previous display can be restored by the
  3563. client command 'restore'.
  3564. .LP
  3565. .TP 8
  3566. 0, space, return
  3567. Makes a move on the board.  (Send the coordinates of the cursor to the
  3568. server.)
  3569. .LP
  3570. .TP 8
  3571. c
  3572. Clears the marks on the board which indicate which piece was played
  3573. last.  
  3574. .LP
  3575. .TP 8
  3576. comma, period (, and .)
  3577. Move backwards (comma) or forwards (period) through the moves in the
  3578. game currently displayed on the board.  If a new move arrives while you
  3579. are observing the game like this, you will be bounced back to the end
  3580. of the game.  
  3581. .LP
  3582. .TP 8
  3583. <, >
  3584. Move backwards or forwards by sets of ten moves
  3585. through the game currently displayed on the board.  
  3586. .LP
  3587. .TP 8
  3588. s, e
  3589. Jump to start (s) or end (e) of the game displayed on the board.
  3590. .LP
  3591. Commands in the server window are words rather than single characters.
  3592. These commands will work in the full screen mode as well when appropriate.
  3593. The backspace and delete keys will remove the last character you
  3594. typed, and ^U will kill the whole line.  
  3595. .LP
  3596. .TP 4
  3597. helpigc 
  3598. Display a brief help screen.
  3599. .LP
  3600. .TP 4
  3601. observe <n>
  3602. Begin observing game n.  If you are already observing a game, this
  3603. command will stop observing that game and begin observing game n.
  3604. If you are observing game n, then this command will stop observing
  3605. game n.  This command can be abbreviated as 'ob'. 
  3606. .LP
  3607. .TP 4
  3608. unobserve
  3609. Stop observing the game you are watching.  This command can be
  3610. abbreviated as 'unob'.  
  3611. .LP
  3612. .TP 4
  3613. peek <n>
  3614. Peeks at game n.  Fetches all the moves from that game without
  3615. observing so that you can play the game back from the start, or just
  3616. see what it looks like.
  3617. .LP
  3618. .TP 4
  3619. restore
  3620. Restores the active game display which was on the board before
  3621. a 'look' or 'status' command.  This command is only valid when the
  3622. upper left corner of the screen says "sta". 
  3623. .LP
  3624. .TP 4
  3625. goto <n>
  3626. Goes to move n in the game displayed on the board.
  3627. .LP
  3628. .TP 4
  3629. clear
  3630. Clears the server window
  3631. .LP
  3632. .TP 4
  3633. noboard
  3634. Removes the board and returns to full screen interaction with the
  3635. server.
  3636. .LP
  3637. .TP 4
  3638. user <name>
  3639. Prints the line for <name> from the output of the last who command.
  3640. .LP
  3641. .TP 4
  3642. sort <sort-type>
  3643. Sets the sorting method for output from the server's 'who' command. 
  3644. Available sorting methods are: none, rank, name, and game.  The 'none'
  3645. type does no sorting.  The 'name' type sorts by name, 'rank' sorts by
  3646. rank, 'idle' sorts by idle time and 'game' sorts first by 
  3647. the game a player is playing in,
  3648. second by whether a player is open for games, and finally by rank.  
  3649. The default sorting method is 'name'. 
  3650. .LP
  3651. .TP4
  3652. inverse
  3653. Switch board display to inverse video.  (This is the default display).
  3654. .LP
  3655. .TP 4
  3656. noinverse
  3657. Switch board display to regular video.
  3658. .LP
  3659. .TP 4
  3660. invedge
  3661. Display edges with inverse video.
  3662. .LP
  3663. .TP 4
  3664. noinvedge
  3665. Display edges with normal video. (This is the default).
  3666. .LP
  3667. .TP 4
  3668. chars <list>
  3669. Sets the board characters.  The order is
  3670. empty, black, white, dame, black territory, white territory, hoshi
  3671. point, border.  The characters should appear without spaces betwee
  3672. them.  The default character set is .#O?+-+ with a space for the
  3673. border character.
  3674. .LP
  3675. .TP 4
  3676. border <char>
  3677. Sets the border character to char.  If char is omitted then the border
  3678. is turned off.  (This is the default.)
  3679. .LP
  3680. .TP 4
  3681. beeps <n>
  3682. Sets the number of beeps sent when sending a beep.  The
  3683. default is one.
  3684. .LP
  3685. .TP 4
  3686. saybeep
  3687. Causes 
  3688. .B igc
  3689. to beep when your opponent says something to you during a game using
  3690. the say command.  Does not cause
  3691. messages sent with the tell command to beep.
  3692. .LP
  3693. .TP 4
  3694. nosaybeep
  3695. Do not beep when your opponent says something to you with the say
  3696. command.  (This is the default.)
  3697. .LP
  3698. .TP 4
  3699. tellbeep
  3700. Causes
  3701. .B igc
  3702. to beep if anyone tells you anything at any time.  
  3703. Does not cause messages sent with the say command to beep.
  3704. .LP
  3705. .TP 4
  3706. notellbeep
  3707. Do not beep when people tell things to you.  (This is the default.)
  3708. .LP
  3709. .TP 4
  3710. prefix <text>
  3711. Adds text to every line you type to the server.  All characters before
  3712. your text will be used in the prefix.  The purpose of this command is
  3713. to make it easier to hold conversations with someone. 
  3714. To talk with goplayer, you might type 'prefix tell goplayer ' (note
  3715. the extra space).  All subsequent lines would be sent to goplayer.
  3716. If you start a line with '!' then the prefix will not be used. 
  3717. To turn off the prefix, type '!prefix'. 
  3718. When the prefix is active and the board is displayed, the prefix text
  3719. is displayed at the bottom of the server window.
  3720. .LP
  3721. .TP 4
  3722. edgemarks
  3723. Turns on display of marks at the edge of the board to indicate last
  3724. move.
  3725. .LP
  3726. .TP 4
  3727. noedgemarks
  3728. Turns off display of marks at the edge of the board to indicate last
  3729. move. (This is the default.)
  3730. .LP
  3731. .TP 4
  3732. piecemarks
  3733. Turns on display of marks around the last stone played.  (This is
  3734. the default.)
  3735. .LP
  3736. .TP 4
  3737. nopiecemarks
  3738. Turns off display of marks around the last stone played.
  3739. .SH CUSTOMIZATION
  3740. The file 
  3741. .B .igcrc
  3742. is used to do initialization.  You do not need to have this file, but
  3743. it can set up 
  3744. .B igc
  3745. to suit your desires and it can automatically log you in.
  3746. You create this file in your home directory yourself, using 
  3747. a text editor (emacs, vi).  
  3748. The following server window commands are supported in the 
  3749. .B .igcrc
  3750. file: inverse, noinverse, invedge, noinvedge, beeps, saybeep, 
  3751. nosaybeep, chars, border, sort.  
  3752. They can be used to configure the display as desired.
  3753. .LP
  3754. Some special commands are supported as well:
  3755. .LP
  3756. .TP 4
  3757. login <name>
  3758. Causes 
  3759. .B igc
  3760. to automatically send <name> as your login name when the connection is
  3761. established.  (This is suppressed by the \-s option.)
  3762. .LP
  3763. .TP 4
  3764. password <password>
  3765. Causes 
  3766. .B igc
  3767. to send <password> as your password.  If you use this command, you
  3768. should make sure that your 
  3769. .B .igcrc
  3770. file is not world readable.  Use the command 'chmod 600 .igcrc' to 
  3771. set the insure that this file is not world readable.
  3772. (Transmission of <password> is supressed by the \-s option.)
  3773. .LP
  3774. .TP 4
  3775. site# <name> <address> <port>
  3776. The program keeps a table of ten sites labeled site0 through site9.  
  3777. By using this command with '#' replaced by the appropriate digit, you
  3778. can define new servers.  A server has <name> as its shorthand
  3779. reference, <address> as a fully qualified internet address, and port
  3780. number <port>.  By changing site0, you can change the default site
  3781. which is used if
  3782. .B igc
  3783. is invoked without parameters.  By default, the first three sites are
  3784. set as described under command line options.  The remaining seven
  3785. sites are undefined.  
  3786. .SH BUGS
  3787. .LP
  3788. Text the server sends before the Login: prompt is not displayed
  3789. .LP
  3790. Login message isn't displayed when logging into accounts not in client
  3791. mode
  3792. .LP
  3793. Sometimes you'll get a "premature move" error when starting a game.
  3794. If this happens you must restart your game.
  3795. .LP
  3796. The server doesn't correctly mark the ends of games, so if a game
  3797. ends while you are playing/observing, the client may still think
  3798. you are playing/observing.  The number in the upper left will
  3799. say '--' if the client realizes you are not doing anything.  If
  3800. it doesn't, press return a few times in the server window.
  3801. .LP
  3802. If someone who is playing a game changes their rank, the change
  3803. will not be reflected on the screens of other people watching or
  3804. playing that game.  
  3805. .LP
  3806. If komi changes during a game, the observers will not see the change.
  3807. (The players will.)
  3808. .LP
  3809. Sometimes when you observe a game, a move may get lost. 
  3810. .LP
  3811. The program cannot handle boards larger than 19x19.
  3812. .SH AUTHOR
  3813. Adrian Mariano (adrian@u.washington.edu, adrian on IGS)
  3814. .SH SEE ALSO
  3815. LaTeX and Postscript documentation for the IGS is available on
  3816. ftp.u.washington.edu in public/go/prog/igs.tex.Z and public/go/prog/igs.ps.Z.  
  3817. .LP
  3818. Other programs: mgt, pcigc, stigc, xigc, xgospel
  3819.  
  3820. SHAR_EOF
  3821. fi
  3822. exit 0
  3823. #    End of shell archive
  3824.